From 1c5363153dc7ae694404e7732b4ce36eecc94ca7 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 12 Sep 2005 09:15:14 -0500 Subject: [SCSI] blacklist REPORT LUNS usage on transtec arrays They report being SCSI-3 but seem to give back rubbish to a REPORT_LUNS command. Force them to be sequentially scanned. Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 07b554a..64fc9e2 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -110,6 +110,7 @@ static struct { {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, + {"transtec", "T5008", "0001", BLIST_NOREPORTLUN }, {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ -- cgit v0.10.2 From 154fb614df83086ceb18a2c19908154e78d4dc98 Mon Sep 17 00:00:00 2001 From: Dave C Boutcher Date: Tue, 13 Sep 2005 10:09:02 -0500 Subject: [SCSI] ibmvscsi compatibility fix Linda Xie ever so gently pointed out that she had a patch to preserve compatibility with older SLES targets, and I told her we didn't need to push it to mainline. This patch explicitly checks the version of the IBMVSCSI target and ensures that large scatterlists are not sent to older targets. Signed-off-by: Linda Xie Signed-off-by: Dave Boutcher Signed-off-by: James Bottomley diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5b14934..ff25210 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -727,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) if (hostdata->madapter_info.port_max_txu[0]) hostdata->host->max_sectors = hostdata->madapter_info.port_max_txu[0] >> 9; + + if (hostdata->madapter_info.os_type == 3 && + strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { + printk("ibmvscsi: host (Ver. %s) doesn't support large" + "transfers\n", + hostdata->madapter_info.srp_version); + printk("ibmvscsi: limiting scatterlists to %d\n", + MAX_INDIRECT_BUFS); + hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; + } } } -- cgit v0.10.2 From a89f29f6ea8dba0b7c4ae5d1d0b43de6cb500ea6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 30 Aug 2005 11:48:07 -0500 Subject: [SCSI] aic7xxx: move to dma_get_required_mask() and correct 39 bit assumptions This patch moves aic7xxx over to the dma_get_required_mask() API and dumps its open coded memory check. It also appears from this bug: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=167049 That 39 bit addressing doesn't work on older cards. I surmise that the AHC_LARGE_SCBS flag is the one that marks cards capable of using 39 bit addressing, so I also folded that check into the code. Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index c932b3b..876d1de 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1109,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa return (0); } -uint64_t -ahc_linux_get_memsize(void) -{ - struct sysinfo si; - - si_meminfo(&si); - return ((uint64_t)si.totalram << PAGE_SHIFT); -} - /* * Place the SCSI bus into a known state by either resetting it, * or forcing transfer negotiations on the next command to any diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index c529962..be9edbe 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) int ahc_linux_register_host(struct ahc_softc *, struct scsi_host_template *); -uint64_t ahc_linux_get_memsize(void); - /*************************** Pretty Printing **********************************/ struct info_str { char *buffer; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 0d44a69..3ce77dd 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -180,6 +180,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ahc_pci_identity *entry; char *name; int error; + struct device *dev = &pdev->dev; pci = pdev; entry = ahc_find_pci_device(pci); @@ -209,11 +210,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); if (sizeof(dma_addr_t) > 4 - && ahc_linux_get_memsize() > 0x80000000 - && pci_set_dma_mask(pdev, mask_39bit) == 0) { + && ahc->features & AHC_LARGE_SCBS + && dma_set_mask(dev, mask_39bit) == 0 + && dma_get_required_mask(dev) > DMA_32BIT_MASK) { ahc->flags |= AHC_39BIT_ADDRESSING; } else { - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { + if (dma_set_mask(dev, DMA_32BIT_MASK)) { printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); return (-ENODEV); } -- cgit v0.10.2 From 9cb90de84b1d9c4686f12042a3696df38e0114c3 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Wed, 14 Sep 2005 18:03:26 +0200 Subject: [PATCH] s390: TSO related fixes in qeth driver Jeff, I'm sorry seems that they have not been sent out either ... ok here they come ... [patch 3/4] s390: TSO related fixes in qeth driver From: Frank Pavlic TSO related fixes : - changing value of large_send attribute while network traffic is running caused program check and thus device recovery. - Due to hardware restriction discard packet when it exceeds 60K otherwise qeth will cause program checks and thus traffic stall when trying to send such huge packets. Signed-off-by: Frank Pavlic diffstat: qeth.h | 4 ++-- qeth_main.c | 33 +++++++++++++++++++++------------ qeth_sys.c | 10 +++------- 3 files changed, 26 insertions(+), 21 deletions(-) Signed-off-by: Jeff Garzik diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 3a02856..5c67d53 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.139 $" +#define VERSION_QETH_H "$Revision: 1.141 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -1172,7 +1172,7 @@ extern int qeth_realloc_buffer_pool(struct qeth_card *, int); extern int -qeth_set_large_send(struct qeth_card *); +qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); extern void qeth_fill_header(struct qeth_card *, struct qeth_hdr *, diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 79c74f3..6f784c3 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.219 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.219 $ $Date: 2005/05/04 20:19:18 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.214 $" +#define VERSION_QETH_C "$Revision: 1.219 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -3795,12 +3795,16 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { + int rc; #ifdef CONFIG_QETH_VLAN u16 *tag; #endif QETH_DBF_TEXT(trace, 6, "prepskb"); + rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); + if (rc) + return rc; #ifdef CONFIG_QETH_VLAN if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { @@ -4251,7 +4255,8 @@ out: } static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) +qeth_get_elements_no(struct qeth_card *card, void *hdr, + struct sk_buff *skb, int elems) { int elements_needed = 0; @@ -4261,9 +4266,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) if (elements_needed == 0 ) elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); + "IP packet (Number=%d / Length=%d). Discarded.\n", + (elements_needed+elems), skb->len); return 0; } return elements_needed; @@ -4337,9 +4343,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); - if (!elements_needed) + int elems = qeth_get_elements_no(card,(void*) hdr, skb, + elements_needed); + if (!elems) return -EINVAL; + elements_needed += elems; } if (card->info.type != QETH_CARD_TYPE_IQD) @@ -7038,14 +7046,16 @@ qeth_setrouting_v6(struct qeth_card *card) } int -qeth_set_large_send(struct qeth_card *card) +qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) { int rc = 0; - if (card->dev == NULL) + if (card->dev == NULL) { + card->options.large_send = type; return 0; - + } netif_stop_queue(card->dev); + card->options.large_send = type; switch (card->options.large_send) { case QETH_LARGE_SEND_EDDP: card->dev->features |= NETIF_F_TSO | NETIF_F_SG; @@ -7066,7 +7076,6 @@ qeth_set_large_send(struct qeth_card *card) card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); break; } - netif_wake_queue(card->dev); return rc; } diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 98bedb0..4bdc904 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.53 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.53 $"; /*****************************************************************************/ /* */ @@ -771,9 +771,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con if (!card) return -EINVAL; - tmp = strsep((char **) &buf, "\n"); - if (!strcmp(tmp, "no")){ type = QETH_LARGE_SEND_NO; } else if (!strcmp(tmp, "EDDP")) { @@ -786,10 +784,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con } if (card->options.large_send == type) return count; - card->options.large_send = type; - if ((rc = qeth_set_large_send(card))) + if ((rc = qeth_set_large_send(card, type))) return rc; - return count; } -- cgit v0.10.2 From f3d242e8f2bf12cb45eb35b7d2e69483d1209b13 Mon Sep 17 00:00:00 2001 From: Frank Pavlic Date: Wed, 14 Sep 2005 18:05:31 +0200 Subject: [PATCH] s390: qeth driver fixes [patch 4/4] s390: qeth driver fixes . From: Frank Pavlic - Clear read channel first prior to using ccw_device_set_offline. - use QETH_DBF_TEXT instead of QETH_DBF_SPRINTF - invoke qeth_halt_channel and qeth_clear_channel for all channels, even if halt/clear for one of the channel fails. - enable qeth_arp_query function for GuestLAN devices Signed-off-by: Frank Pavlic diffstat: qeth.h | 2 - qeth_main.c | 106 +++++++++++++++++++++++++----------------------------------- qeth_sys.c | 11 +++--- 3 files changed, 53 insertions(+), 66 deletions(-) Signed-off-by: Jeff Garzik diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 5c67d53..2ad4797 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.141 $" +#define VERSION_QETH_H "$Revision: 1.142 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 6f784c3..86582cf 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.219 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.219 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ * * 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 @@ -29,14 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/*** - * eye catcher; just for debugging purposes - */ -void volatile -qeth_eyecatcher(void) -{ - return; -} #include #include @@ -80,7 +72,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.219 $" +#define VERSION_QETH_C "$Revision: 1.224 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, queue->card->perf_stats.outbound_do_qdio_start_time; #endif if (rc){ - QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " - "returned error (%i) on device %s.", - rc, CARD_DDEV_ID(queue->card)); QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); queue->card->stats.tx_errors += count; /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ @@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, QETH_DBF_TEXT(trace, 6, "qdouhdl"); if (status & QDIO_STATUS_LOOK_FOR_ERROR) { if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ - QETH_DBF_SPRINTF(trace, 2, "On device %s: " - "received active check " - "condition (0x%08x).", - CARD_BUS_ID(card), status); - QETH_DBF_TEXT(trace, 2, "chkcond"); + QETH_DBF_TEXT(trace, 2, "achkcond"); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(trace, 2, "%08x", status); netif_stop_queue(card->dev); qeth_schedule_recovery(card); @@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel) static int qeth_halt_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"haltchs"); - if ((rc = qeth_halt_channel(&card->read))) - return rc; - if ((rc = qeth_halt_channel(&card->write))) - return rc; - return qeth_halt_channel(&card->data); + rc1 = qeth_halt_channel(&card->read); + rc2 = qeth_halt_channel(&card->write); + rc3 = qeth_halt_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int qeth_clear_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"clearchs"); - if ((rc = qeth_clear_channel(&card->read))) - return rc; - if ((rc = qeth_clear_channel(&card->write))) - return rc; - return qeth_clear_channel(&card->data); + rc1 = qeth_clear_channel(&card->read); + rc2 = qeth_clear_channel(&card->write); + rc3 = qeth_clear_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int @@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card) } if ((rc = qeth_cm_enable(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_cm_setup(card))){ QETH_DBF_TEXT_(setup, 2, "3err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_enable(card))){ QETH_DBF_TEXT_(setup, 2, "4err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_setup(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_alloc_qdio_buffers(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_qdio_establish(card))){ QETH_DBF_TEXT_(setup, 2, "6err%d", rc); @@ -4281,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int ipv = 0; int cast_type; struct qeth_qdio_out_q *queue; - struct qeth_hdr *hdr; + struct qeth_hdr *hdr = NULL; int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; @@ -4512,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) QETH_DBF_TEXT(trace,3,"arpstnoe"); - /* TODO: really not supported by GuestLAN? */ + /* + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -4689,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata) QETH_DBF_TEXT(trace,3,"arpquery"); - /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ - /*if (card->info.guestlan) - return -EOPNOTSUPP; */ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { PRINT_WARN("ARP processing not supported " @@ -4902,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) QETH_DBF_TEXT(trace,3,"arpadent"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4945,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry QETH_DBF_TEXT(trace,3,"arprment"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4986,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"arpflush"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -8266,7 +8252,6 @@ qeth_init(void) { int rc=0; - qeth_eyecatcher(); PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", version, VERSION_QETH_C, VERSION_QETH_H, VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, @@ -8347,7 +8332,6 @@ again: printk("qeth: removed\n"); } -EXPORT_SYMBOL(qeth_eyecatcher); module_init(qeth_init); module_exit(qeth_exit); MODULE_AUTHOR("Frank Pavlic "); diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 4bdc904..dda105b 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.53 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.53 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $"; /*****************************************************************************/ /* */ @@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c if (!card) return -EINVAL; + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); + return -EPERM; + } if (((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) || - (card->info.type != QETH_CARD_TYPE_OSAE)) + (card->state != CARD_STATE_RECOVER))) return -EPERM; i = simple_strtoul(buf, &tmp, 16); -- cgit v0.10.2 From 186d330e682210100c671355580a8592e4a21692 Mon Sep 17 00:00:00 2001 From: Timothy Thelin Date: Tue, 13 Sep 2005 19:56:28 -0700 Subject: [SCSI] scsi: sd, sr, st, and scsi_lib all fail to copy cmd_len to new cmd This fixes an issue in scsi command initialization from a request where sd, sr, st, and scsi_lib all fail to copy the request's cmd_len to the scsi command's cmd_len field. Signed-off-by: Timothy Thelin Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 863bb64..f9026d0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1268,6 +1268,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) } } else { memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); + cmd->cmd_len = req->cmd_len; if (rq_data_dir(req) == WRITE) cmd->sc_data_direction = DMA_TO_DEVICE; else if (req->data_len) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index de564b3..9a1dc0c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -235,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) return 0; memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); + SCpnt->cmd_len = rq->cmd_len; if (rq_data_dir(rq) == WRITE) SCpnt->sc_data_direction = DMA_TO_DEVICE; else if (rq->data_len) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ce63fc8..561901b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -326,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) return 0; memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); + SCpnt->cmd_len = rq->cmd_len; if (!rq->data_len) SCpnt->sc_data_direction = DMA_NONE; else if (rq_data_dir(rq) == WRITE) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a93308a..d001c04 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4206,6 +4206,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt) return 0; memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); + SCpnt->cmd_len = rq->cmd_len; if (rq_data_dir(rq) == WRITE) SCpnt->sc_data_direction = DMA_TO_DEVICE; -- cgit v0.10.2 From d39a942c3f4061d2218dcadf79ce10010dbcdb3c Mon Sep 17 00:00:00 2001 From: "Randy.Dunlap" Date: Tue, 13 Sep 2005 21:43:56 -0700 Subject: [SCSI] scsi: 2 drivers need MODULE_LICENSE() Modules need a license to prevent kernel tainting. Signed-off-by: Randy Dunlap Signed-off-by: James Bottomley diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index fa652f8a..d59d449 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = { .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" + +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 6e54c7d..19392f6 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -460,6 +460,8 @@ MODULE_PARM(adisplay, "1i"); MODULE_PARM(normal, "1i"); MODULE_PARM(ansi, "1i"); #endif + +MODULE_LICENSE("GPL"); #endif /*counter of concurrent disk read/writes, to turn on/off disk led */ static int disk_rw_in_progress = 0; -- cgit v0.10.2 From 59897dad98d63ac15e1e36fcc3a107c892b1826c Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 14 Sep 2005 12:57:42 -0400 Subject: [SCSI] fix sym scsi boot hang On Wed, 2005-09-14 at 18:06 +1000, Anton Blanchard wrote: > And in particular it looks like the scsi_unprep_request in > scsi_queue_insert is causing it. The following patch fixes the boot > problems on the vscsi machine: OK, my fault. Your fix is almost correct .. I was going to do this eventually, honest, because there's no need to unprep and reprep a command that comes in through scsi_queue_insert(). However, I decided to leave it in to exercise the scsi_unprep_request() path just to make sure it was working. What's happening, I think, is that we also use this path for retries. Since we kill and reget the command each time, the retries decrement is never seen, so we're retrying forever. Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f9026d0..0c6924e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -140,14 +140,12 @@ static void scsi_unprep_request(struct request *req) * commands. * Notes: This could be called either from an interrupt context or a * normal process context. - * Notes: Upon return, cmd is a stale pointer. */ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) { struct Scsi_Host *host = cmd->device->host; struct scsi_device *device = cmd->device; struct request_queue *q = device->request_queue; - struct request *req = cmd->request; unsigned long flags; SCSI_LOG_MLQUEUE(1, @@ -188,9 +186,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) * function. The SCSI request function detects the blocked condition * and plugs the queue appropriately. */ - scsi_unprep_request(req); spin_lock_irqsave(q->queue_lock, flags); - blk_requeue_request(q, req); + blk_requeue_request(q, cmd->request); spin_unlock_irqrestore(q->queue_lock, flags); scsi_run_queue(q); -- cgit v0.10.2 From 3c05d92ed49f644d1f5a960fa48637d63b946016 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 14 Sep 2005 20:50:35 -0700 Subject: [TCP]: Compute in_sacked properly when we split up a TSO frame. The problem is that the SACK fragmenting code may incorrectly call tcp_fragment() with a length larger than the skb->len. This happens when the skb on the transmit queue completely falls to the LHS of the SACK. And add a BUG() check to tcp_fragment() so we can spot this kind of error more quickly in the future. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 29222b96..a7537c7 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -979,14 +979,19 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if (!before(TCP_SKB_CB(skb)->seq, end_seq)) break; + in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && + !before(end_seq, TCP_SKB_CB(skb)->end_seq); + pcount = tcp_skb_pcount(skb); - if (pcount > 1 && - (after(start_seq, TCP_SKB_CB(skb)->seq) || - before(end_seq, TCP_SKB_CB(skb)->end_seq))) { + if (pcount > 1 && !in_sack && + after(TCP_SKB_CB(skb)->end_seq, start_seq)) { unsigned int pkt_len; - if (after(start_seq, TCP_SKB_CB(skb)->seq)) + in_sack = !after(start_seq, + TCP_SKB_CB(skb)->seq); + + if (!in_sack) pkt_len = (start_seq - TCP_SKB_CB(skb)->seq); else @@ -999,9 +1004,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ fack_count += pcount; - in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && - !before(end_seq, TCP_SKB_CB(skb)->end_seq); - sacked = TCP_SKB_CB(skb)->sacked; /* Account D-SACK for retransmitted packet. */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c10e443..b018e31 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -435,6 +435,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss int nsize, old_factor; u16 flags; + BUG_ON(len >= skb->len); + nsize = skb_headlen(skb) - len; if (nsize < 0) nsize = 0; -- cgit v0.10.2 From 20ae975dfd54de581287b2ca8a1ad97099ab0396 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Sep 2005 20:52:37 -0700 Subject: [NETLINK]: Reserve a slot for NETLINK_GENERIC. As requested by Jamal. Signed-off-by: David S. Miller diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 7bbd259..bdebdc5 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -20,6 +20,7 @@ #define NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ +#define NETLINK_GENERIC 16 #define MAX_LINKS 32 -- cgit v0.10.2 From de9daad90ecb54f3c37c3f8967d581e20d927539 Mon Sep 17 00:00:00 2001 From: Denis Lukianov Date: Wed, 14 Sep 2005 20:53:42 -0700 Subject: [MCAST]: Fix MCAST_EXCLUDE line dupes This patch fixes line dupes at /ipv4/igmp.c and /ipv6/mcast.c in the 2.6 kernel, where MCAST_EXCLUDE is mistakenly used instead of MCAST_INCLUDE. Signed-off-by: Denis Lukianov Signed-off-by: David L Stevens Signed-off-by: David S. Miller diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 44607f4..70c44e4 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1603,7 +1603,7 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc) } pmc->sources = NULL; pmc->sfmode = MCAST_EXCLUDE; - pmc->sfcount[MCAST_EXCLUDE] = 0; + pmc->sfcount[MCAST_INCLUDE] = 0; pmc->sfcount[MCAST_EXCLUDE] = 1; } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 29fed6e..519899f 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1968,7 +1968,7 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc) } pmc->mca_sources = NULL; pmc->mca_sfmode = MCAST_EXCLUDE; - pmc->mca_sfcount[MCAST_EXCLUDE] = 0; + pmc->mca_sfcount[MCAST_INCLUDE] = 0; pmc->mca_sfcount[MCAST_EXCLUDE] = 1; } -- cgit v0.10.2 From 1c011bed5f49ce9e6193b18b226106a41ecfa95c Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Wed, 14 Sep 2005 20:55:16 -0700 Subject: [BRIDGE-NF]: Fix iptables redirect on bridge interface Here's a slightly altered patch, originally from Mark Glines who diagnosed and fixed the problem. Signed-off-by: Bart De Schuymer Signed-off-by: David S. Miller diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 2d52fee..d8e36b7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -214,9 +214,11 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) .tos = RT_TOS(iph->tos)} }, .proto = 0}; if (!ip_route_output_key(&rt, &fl)) { - /* Bridged-and-DNAT'ed traffic doesn't - * require ip_forwarding. */ - if (((struct dst_entry *)rt)->dev == dev) { + /* - Bridged-and-DNAT'ed traffic doesn't + * require ip_forwarding. + * - Deal with redirected traffic. */ + if (((struct dst_entry *)rt)->dev == dev || + rt->rt_type == RTN_LOCAL) { skb->dst = (struct dst_entry *)rt; goto bridged_dnat; } -- cgit v0.10.2 From f5e229db9cdb27f83594712ca4bb98d9377eb6ed Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 14 Sep 2005 21:04:23 -0700 Subject: [IPVS]: Really invalidate persistent templates Agostino di Salle noticed that persistent templates are not invalidated due to buggy optimization. Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index e11952e..5994521 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -467,7 +467,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct) /* * Invalidate the connection template */ - if (ct->cport) { + if (ct->vport != 65535) { if (ip_vs_conn_unhash(ct)) { ct->dport = 65535; ct->vport = 65535; -- cgit v0.10.2 From 87375ab47cd0ba04124c6d3fd80db5c368f5dcb6 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Wed, 14 Sep 2005 21:08:51 -0700 Subject: [IPVS]: ip_vs_ftp breaks connections using persistence ip_vs_ftp when loaded can create NAT connections with unknown client port for passive FTP. For such expectations we lookup with cport=0 on incoming packet but it matches the format of the persistence templates causing packets to other persistent virtual servers to be forwarded to real server without creating connection. Later the reply packets are treated as foreign and not SNAT-ed. This patch changes the connection lookup for packets from clients: * introduce IP_VS_CONN_F_TEMPLATE connection flag to mark the connection as template * create new connection lookup function just for templates - ip_vs_ct_in_get * make sure ip_vs_conn_in_get hits only connections with IP_VS_CONN_F_NO_CPORT flag set when s_port is 0. By this way we avoid returning template when looking for cport=0 (ftp) Signed-off-by: Julian Anastasov Signed-off-by: David S. Miller diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e426641..06b4235 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -84,6 +84,7 @@ #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ #define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */ #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ +#define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ /* Move it to better place one day, for now keep it unique */ #define NFC_IPVS_PROPERTY 0x10000 @@ -739,6 +740,8 @@ enum { extern struct ip_vs_conn *ip_vs_conn_in_get (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); +extern struct ip_vs_conn *ip_vs_ct_in_get +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); extern struct ip_vs_conn *ip_vs_conn_out_get (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 5994521..f828fa2 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -196,6 +196,7 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { if (s_addr==cp->caddr && s_port==cp->cport && d_port==cp->vport && d_addr==cp->vaddr && + ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && protocol==cp->protocol) { /* HIT */ atomic_inc(&cp->refcnt); @@ -227,6 +228,40 @@ struct ip_vs_conn *ip_vs_conn_in_get return cp; } +/* Get reference to connection template */ +struct ip_vs_conn *ip_vs_ct_in_get +(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port) +{ + unsigned hash; + struct ip_vs_conn *cp; + + hash = ip_vs_conn_hashkey(protocol, s_addr, s_port); + + ct_read_lock(hash); + + list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { + if (s_addr==cp->caddr && s_port==cp->cport && + d_port==cp->vport && d_addr==cp->vaddr && + cp->flags & IP_VS_CONN_F_TEMPLATE && + protocol==cp->protocol) { + /* HIT */ + atomic_inc(&cp->refcnt); + goto out; + } + } + cp = NULL; + + out: + ct_read_unlock(hash); + + IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", + ip_vs_proto_name(protocol), + NIPQUAD(s_addr), ntohs(s_port), + NIPQUAD(d_addr), ntohs(d_port), + cp?"hit":"not hit"); + + return cp; +} /* * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. @@ -367,7 +402,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) atomic_read(&dest->refcnt)); /* Update the connection counters */ - if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) { + if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) { /* It is a normal connection, so increase the inactive connection counter because it is in TCP SYNRECV state (inactive) or other protocol inacive state */ @@ -406,7 +441,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) atomic_read(&dest->refcnt)); /* Update the connection counters */ - if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) { + if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) { /* It is a normal connection, so decrease the inactconns or activeconns counter */ if (cp->flags & IP_VS_CONN_F_INACTIVE) { @@ -776,7 +811,7 @@ void ip_vs_random_dropentry(void) ct_write_lock_bh(hash); list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { - if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT)) + if (cp->flags & IP_VS_CONN_F_TEMPLATE) /* connection template */ continue; diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 3ac7eec..981cc32 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -243,10 +243,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc, if (ports[1] == svc->port) { /* Check if a template already exists */ if (svc->port != FTPPORT) - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, ports[1]); else - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, 0); if (!ct || !ip_vs_check_template(ct)) { @@ -272,14 +272,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc, iph->daddr, ports[1], dest->addr, dest->port, - 0, + IP_VS_CONN_F_TEMPLATE, dest); else ct = ip_vs_conn_new(iph->protocol, snet, 0, iph->daddr, 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); if (ct == NULL) return NULL; @@ -298,10 +298,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc, * port zero template: */ if (svc->fwmark) - ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0, + ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0, htonl(svc->fwmark), 0); else - ct = ip_vs_conn_in_get(iph->protocol, snet, 0, + ct = ip_vs_ct_in_get(iph->protocol, snet, 0, iph->daddr, 0); if (!ct || !ip_vs_check_template(ct)) { @@ -326,14 +326,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc, snet, 0, htonl(svc->fwmark), 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); else ct = ip_vs_conn_new(iph->protocol, snet, 0, iph->daddr, 0, dest->addr, 0, - 0, + IP_VS_CONN_F_TEMPLATE, dest); if (ct == NULL) return NULL; diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 574d1f5..2e5ced3 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -297,16 +297,24 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); for (i=0; inr_conns; i++) { + unsigned flags; + s = (struct ip_vs_sync_conn *)p; - cp = ip_vs_conn_in_get(s->protocol, - s->caddr, s->cport, - s->vaddr, s->vport); + flags = ntohs(s->flags); + if (!(flags & IP_VS_CONN_F_TEMPLATE)) + cp = ip_vs_conn_in_get(s->protocol, + s->caddr, s->cport, + s->vaddr, s->vport); + else + cp = ip_vs_ct_in_get(s->protocol, + s->caddr, s->cport, + s->vaddr, s->vport); if (!cp) { cp = ip_vs_conn_new(s->protocol, s->caddr, s->cport, s->vaddr, s->vport, s->daddr, s->dport, - ntohs(s->flags), NULL); + flags, NULL); if (!cp) { IP_VS_ERR("ip_vs_conn_new failed\n"); return; @@ -315,11 +323,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) } else if (!cp->dest) { /* it is an entry created by the synchronization */ cp->state = ntohs(s->state); - cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED; + cp->flags = flags | IP_VS_CONN_F_HASHED; } /* Note that we don't touch its state and flags if it is a normal entry. */ - if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) { + if (flags & IP_VS_CONN_F_SEQ_MASK) { opt = (struct ip_vs_sync_conn_options *)&s[1]; memcpy(&cp->in_seq, opt, sizeof(*opt)); p += FULL_CONN_SIZE; -- cgit v0.10.2 From 40796c5e8f2a93008e9034b3110a7e7b1fa0fba0 Mon Sep 17 00:00:00 2001 From: David L Stevens Date: Wed, 14 Sep 2005 21:10:20 -0700 Subject: [IPV6]: Fix per-socket multicast filtering in sk_reuse case per-socket multicast filters were not being applied to all sockets in the case of an exact-match bound address, due to an over-exuberant "return" in the look-up code. Fix below. IPv4 does not have this problem. Thanks to Hoerdt Mickael for reporting the bug. Signed-off-by: David L Stevens Signed-off-by: David S. Miller diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69b1468..2b9bf9b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -405,9 +405,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, continue; if (!ipv6_addr_any(&np->rcv_saddr)) { - if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) - return s; - continue; + if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) + continue; } if(!inet6_mc_check(s, loc_addr, rmt_addr)) continue; -- cgit v0.10.2 From 4a805e863d6b9466baf7084e1d6fdbe6e0628d8e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Sep 2005 21:40:00 -0700 Subject: [COMPAT]: Fixup compat_do_execve() Missing acct_update_integrals() and update_mem_hiwater() calls compared to it's native counterpart. Signed-off-by: David S. Miller diff --git a/fs/compat.c b/fs/compat.c index ac3fb9e..a719e15 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include /* siocdevprivate_ioctl */ @@ -1487,6 +1489,8 @@ int compat_do_execve(char * filename, /* execve success */ security_bprm_free(bprm); + acct_update_integrals(current); + update_mem_hiwater(current); kfree(bprm); return retval; } -- cgit v0.10.2 From 4db2ce0199f04b6e99999f22e28ef9a0ae5f0d2f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Sep 2005 21:47:01 -0700 Subject: [LIB]: Consolidate _atomic_dec_and_lock() Several implementations were essentialy a common piece of C code using the cmpxchg() macro. Put the implementation in one spot that everyone can share, and convert sparc64 over to using this. Alpha is the lone arch-specific implementation, which codes up a special fast path for the common case in order to avoid GP reloading which a pure C version would require. Signed-off-by: David S. Miller diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index b22f003..d2703cd 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -908,11 +908,6 @@ config IRQBALANCE The default yes will allow the kernel to do irq load balancing. Saying no will keep the kernel from doing irq load balancing. -config HAVE_DEC_LOCK - bool - depends on (SMP || PREEMPT) && X86_CMPXCHG - default y - # turning this on wastes a bunch of space. # Summit needs it only when NUMA is on config BOOT_IOREMAP diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index 7b1932d..914933e 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -7,4 +7,3 @@ lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \ bitops.o lib-$(CONFIG_X86_USE_3DNOW) += mmx.o -lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c deleted file mode 100644 index 8b81b25..0000000 --- a/arch/i386/lib/dec_and_lock.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * x86 version of "atomic_dec_and_lock()" using - * the atomic "cmpxchg" instruction. - * - * (For CPU's lacking cmpxchg, we use the slow - * generic version, and this one never even gets - * compiled). - */ - -#include -#include -#include - -int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) -{ - int counter; - int newcount; - -repeat: - counter = atomic_read(atomic); - newcount = counter-1; - - if (!newcount) - goto slow_path; - - asm volatile("lock; cmpxchgl %1,%2" - :"=a" (newcount) - :"r" (newcount), "m" (atomic->counter), "0" (counter)); - - /* If the above failed, "eax" will have changed */ - if (newcount != counter) - goto repeat; - return 0; - -slow_path: - spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - spin_unlock(lock); - return 0; -} -EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index ed25d66..945c15a 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -298,11 +298,6 @@ config PREEMPT source "mm/Kconfig" -config HAVE_DEC_LOCK - bool - depends on (SMP || PREEMPT) - default y - config IA32_SUPPORT bool "Support for Linux/x86 binaries" help diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 799407e..cb1af59 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile @@ -15,7 +15,6 @@ lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o lib-$(CONFIG_PERFMON) += carta_random.o lib-$(CONFIG_MD_RAID5) += xor.o -lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o AFLAGS___divdi3.o = AFLAGS___udivdi3.o = -DUNSIGNED diff --git a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c deleted file mode 100644 index c7ce92f..0000000 --- a/arch/ia64/lib/dec_and_lock.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2003 Jerome Marchand, Bull S.A. - * Cleaned up by David Mosberger-Tang - * - * This file is released under the GPLv2, or at your option any later version. - * - * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction. This - * code is an adaptation of the x86 version of "atomic_dec_and_lock()". - */ - -#include -#include -#include -#include - -/* - * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these - * operations have to be done atomically, so that the count doesn't drop to zero without - * acquiring the spinlock first. - */ -int -_atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) -{ - int old, new; - - do { - old = atomic_read(refcount); - new = old - 1; - - if (unlikely (old == 1)) { - /* oops, we may be decrementing to zero, do it the slow way... */ - spin_lock(lock); - if (atomic_dec_and_test(refcount)) - return 1; - spin_unlock(lock); - return 0; - } - } while (cmpxchg(&refcount->counter, old, new) != old); - return 0; -} - -EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 1ef3987e..4d100f3 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -220,11 +220,6 @@ config PREEMPT Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. -config HAVE_DEC_LOCK - bool - depends on (SMP || PREEMPT) - default n - config SMP bool "Symmetric multi-processing support" ---help--- diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0eb71ac..4cd724c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1009,10 +1009,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config HAVE_DEC_LOCK - bool - default y - # # Select some configuration options automatically based on user selections. # diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 21b92b9..0373034 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o \ +lib-y += csum_partial_copy.o memcpy.o promlib.o \ strlen_user.o strncpy_user.o strnlen_user.o obj-y += iomap.o diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c deleted file mode 100644 index fd82c84..0000000 --- a/arch/mips/lib/dec_and_lock.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * MIPS version of atomic_dec_and_lock() using cmpxchg - * - * 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. - */ - -#include -#include -#include -#include - -/* - * This is an implementation of the notion of "decrement a - * reference count, and return locked if it decremented to zero". - * - * This implementation can be used on any architecture that - * has a cmpxchg, and where atomic->value is an int holding - * the value of the atomic (i.e. the high bits aren't used - * for a lock or anything like that). - */ -int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) -{ - int counter; - int newcount; - - for (;;) { - counter = atomic_read(atomic); - newcount = counter - 1; - if (!newcount) - break; /* do it the slow way */ - - newcount = cmpxchg(&atomic->counter, counter, newcount); - if (newcount == counter) - return 0; - } - - spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - spin_unlock(lock); - return 0; -} - -EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 347ea28..776941c 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -26,10 +26,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config HAVE_DEC_LOCK - bool - default y - config PPC bool default y diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index f1e1fb4..50358e4 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for ppc-specific library files.. # -obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o +obj-y := checksum.o string.o strcase.o div64.o obj-$(CONFIG_8xx) += rheap.o obj-$(CONFIG_CPM2) += rheap.o diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c deleted file mode 100644 index b18f0d9..0000000 --- a/arch/ppc/lib/dec_and_lock.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include - -/* - * This is an implementation of the notion of "decrement a - * reference count, and return locked if it decremented to zero". - * - * This implementation can be used on any architecture that - * has a cmpxchg, and where atomic->value is an int holding - * the value of the atomic (i.e. the high bits aren't used - * for a lock or anything like that). - */ -int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) -{ - int counter; - int newcount; - - for (;;) { - counter = atomic_read(atomic); - newcount = counter - 1; - if (!newcount) - break; /* do it the slow way */ - - newcount = cmpxchg(&atomic->counter, counter, newcount); - if (newcount == counter) - return 0; - } - - spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - spin_unlock(lock); - return 0; -} - -EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index deca68a..c658650 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig @@ -28,10 +28,6 @@ config GENERIC_ISA_DMA bool default y -config HAVE_DEC_LOCK - bool - default y - config EARLY_PRINTK bool default y diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile index 76fbfa9..0b6e967 100644 --- a/arch/ppc64/lib/Makefile +++ b/arch/ppc64/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for ppc64-specific library files.. # -lib-y := checksum.o dec_and_lock.o string.o strcase.o +lib-y := checksum.o string.o strcase.o lib-y += copypage.o memcpy.o copyuser.o usercopy.o # Lock primitives are defined as no-ops in include/linux/spinlock.h diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c deleted file mode 100644 index 7b9d4da..0000000 --- a/arch/ppc64/lib/dec_and_lock.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ppc64 version of atomic_dec_and_lock() using cmpxchg - * - * 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. - */ - -#include -#include -#include -#include - -/* - * This is an implementation of the notion of "decrement a - * reference count, and return locked if it decremented to zero". - * - * This implementation can be used on any architecture that - * has a cmpxchg, and where atomic->value is an int holding - * the value of the atomic (i.e. the high bits aren't used - * for a lock or anything like that). - */ -int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) -{ - int counter; - int newcount; - - for (;;) { - counter = atomic_read(atomic); - newcount = counter - 1; - if (!newcount) - break; /* do it the slow way */ - - newcount = cmpxchg(&atomic->counter, counter, newcount); - if (newcount == counter) - return 0; - } - - spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - spin_unlock(lock); - return 0; -} - -EXPORT_SYMBOL(_atomic_dec_and_lock); diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index cd8d39fb..af0e941 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug @@ -33,14 +33,6 @@ config DEBUG_BOOTMEM depends on DEBUG_KERNEL bool "Debug BOOTMEM initialization" -# We have a custom atomic_dec_and_lock() implementation but it's not -# compatible with spinlock debugging so we need to fall back on -# the generic version in that case. -config HAVE_DEC_LOCK - bool - depends on SMP && !DEBUG_SPINLOCK - default y - config MCOUNT bool depends on STACK_DEBUG diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index cbb5e59..fb7a537 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -163,9 +163,6 @@ EXPORT_SYMBOL(atomic64_add); EXPORT_SYMBOL(atomic64_add_ret); EXPORT_SYMBOL(atomic64_sub); EXPORT_SYMBOL(atomic64_sub_ret); -#ifdef CONFIG_SMP -EXPORT_SYMBOL(_atomic_dec_and_lock); -#endif /* Atomic bit operations. */ EXPORT_SYMBOL(test_and_set_bit); diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index d968aeb..c295806 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile @@ -14,6 +14,4 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ copy_in_user.o user_fixup.o memmove.o \ mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o -lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o - obj-y += iomap.o diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S deleted file mode 100644 index 8ee288d..0000000 --- a/arch/sparc64/lib/dec_and_lock.S +++ /dev/null @@ -1,80 +0,0 @@ -/* $Id: dec_and_lock.S,v 1.5 2001/11/18 00:12:56 davem Exp $ - * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()" - * using cas and ldstub instructions. - * - * Copyright (C) 2000 David S. Miller (davem@redhat.com) - */ -#include -#include - - .text - .align 64 - - /* CAS basically works like this: - * - * void CAS(MEM, REG1, REG2) - * { - * START_ATOMIC(); - * if (*(MEM) == REG1) { - * TMP = *(MEM); - * *(MEM) = REG2; - * REG2 = TMP; - * } else - * REG2 = *(MEM); - * END_ATOMIC(); - * } - */ - - .globl _atomic_dec_and_lock -_atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */ -loop1: lduw [%o0], %g2 - subcc %g2, 1, %g7 - be,pn %icc, start_to_zero - nop -nzero: cas [%o0], %g2, %g7 - cmp %g2, %g7 - bne,pn %icc, loop1 - mov 0, %g1 - -out: - membar #StoreLoad | #StoreStore - retl - mov %g1, %o0 -start_to_zero: -#ifdef CONFIG_PREEMPT - ldsw [%g6 + TI_PRE_COUNT], %g3 - add %g3, 1, %g3 - stw %g3, [%g6 + TI_PRE_COUNT] -#endif -to_zero: - ldstub [%o1], %g3 - membar #StoreLoad | #StoreStore - brnz,pn %g3, spin_on_lock - nop -loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ - cmp %g2, %g7 - - be,pt %icc, out - mov 1, %g1 - lduw [%o0], %g2 - subcc %g2, 1, %g7 - be,pn %icc, loop2 - nop - membar #StoreStore | #LoadStore - stb %g0, [%o1] -#ifdef CONFIG_PREEMPT - ldsw [%g6 + TI_PRE_COUNT], %g3 - sub %g3, 1, %g3 - stw %g3, [%g6 + TI_PRE_COUNT] -#endif - - b,pt %xcc, nzero - nop -spin_on_lock: - ldub [%o1], %g3 - membar #LoadLoad - brnz,pt %g3, spin_on_lock - nop - ba,pt %xcc, to_zero - nop - nop diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index e63323e..0969d57 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -277,11 +277,6 @@ source "mm/Kconfig" config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y -config HAVE_DEC_LOCK - bool - depends on SMP - default y - config NR_CPUS int "Maximum number of CPUs (2-256)" range 2 256 diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 68ec030..fd99ddd00 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -178,10 +178,6 @@ EXPORT_SYMBOL(rwsem_down_write_failed_thunk); EXPORT_SYMBOL(empty_zero_page); -#ifdef CONFIG_HAVE_DEC_LOCK -EXPORT_SYMBOL(_atomic_dec_and_lock); -#endif - EXPORT_SYMBOL(die_chain); EXPORT_SYMBOL(register_die_notifier); diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile index 6b26a1c..bba5db6 100644 --- a/arch/x86_64/lib/Makefile +++ b/arch/x86_64/lib/Makefile @@ -10,5 +10,3 @@ lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \ usercopy.o getuser.o putuser.o \ thunk.o clear_page.o copy_page.o bitstr.o bitops.o lib-y += memcpy.o memmove.o memset.o copy_user.o - -lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff --git a/arch/x86_64/lib/dec_and_lock.c b/arch/x86_64/lib/dec_and_lock.c deleted file mode 100644 index ab43394..0000000 --- a/arch/x86_64/lib/dec_and_lock.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * x86 version of "atomic_dec_and_lock()" using - * the atomic "cmpxchg" instruction. - * - * (For CPU's lacking cmpxchg, we use the slow - * generic version, and this one never even gets - * compiled). - */ - -#include -#include - -int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) -{ - int counter; - int newcount; - -repeat: - counter = atomic_read(atomic); - newcount = counter-1; - - if (!newcount) - goto slow_path; - - asm volatile("lock; cmpxchgl %1,%2" - :"=a" (newcount) - :"r" (newcount), "m" (atomic->counter), "0" (counter)); - - /* If the above failed, "eax" will have changed */ - if (newcount != counter) - goto repeat; - return 0; - -slow_path: - spin_lock(lock); - if (atomic_dec_and_test(atomic)) - return 1; - spin_unlock(lock); - return 0; -} diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 2b6257b..7e841aa 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -26,10 +26,6 @@ config RWSEM_XCHGADD_ALGORITHM bool default y -config HAVE_DEC_LOCK - bool - default y - config GENERIC_HARDIRQS bool default y diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c index 2377af0..305a966 100644 --- a/lib/dec_and_lock.c +++ b/lib/dec_and_lock.c @@ -1,7 +1,41 @@ #include #include #include +#include +#ifdef __HAVE_ARCH_CMPXCHG +/* + * This is an implementation of the notion of "decrement a + * reference count, and return locked if it decremented to zero". + * + * This implementation can be used on any architecture that + * has a cmpxchg, and where atomic->value is an int holding + * the value of the atomic (i.e. the high bits aren't used + * for a lock or anything like that). + */ +int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +{ + int counter; + int newcount; + + for (;;) { + counter = atomic_read(atomic); + newcount = counter - 1; + if (!newcount) + break; /* do it the slow way */ + + newcount = cmpxchg(&atomic->counter, counter, newcount); + if (newcount == counter) + return 0; + } + + spin_lock(lock); + if (atomic_dec_and_test(atomic)) + return 1; + spin_unlock(lock); + return 0; +} +#else /* * This is an architecture-neutral, but slow, * implementation of the notion of "decrement @@ -33,5 +67,6 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) spin_unlock(lock); return 0; } +#endif EXPORT_SYMBOL(_atomic_dec_and_lock); -- cgit v0.10.2 From fea2efe3bba15f0aa8f840fbe052699808187cb6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 15 Sep 2005 12:30:11 +0100 Subject: [ARM] Remove PFN_TO_NID for !DISCONTIGMEM Platform classes need not define PFN_TO_NID when DISCONTIGMEM is not selected. Signed-off-by: Russell King diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h index 681b6a6..79c9081 100644 --- a/include/asm-arm/arch-aaec2000/memory.h +++ b/include/asm-arm/arch-aaec2000/memory.h @@ -64,10 +64,6 @@ #define NODE_MAX_MEM_SHIFT 26 #define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif /* CONFIG_DISCONTIGMEM */ #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h index dc4735c..45351f5 100644 --- a/include/asm-arm/arch-iop3xx/memory.h +++ b/include/asm-arm/arch-iop3xx/memory.h @@ -36,6 +36,4 @@ #endif -#define PFN_TO_NID(addr) (0) - #endif diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h index 7e2fea3..c650e6f 100644 --- a/include/asm-arm/arch-lh7a40x/memory.h +++ b/include/asm-arm/arch-lh7a40x/memory.h @@ -85,10 +85,6 @@ (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT) # endif -#else - -# define PFN_TO_NID(addr) (0) - #endif #endif diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h index 84f81e3..ef32d61 100644 --- a/include/asm-arm/arch-omap/memory.h +++ b/include/asm-arm/arch-omap/memory.h @@ -86,6 +86,5 @@ #endif /* CONFIG_ARCH_OMAP1510 */ -#define PHYS_TO_NID(addr) (0) #endif diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h index 217a80b..58bad97 100644 --- a/include/asm-arm/arch-pxa/memory.h +++ b/include/asm-arm/arch-pxa/memory.h @@ -67,10 +67,6 @@ #define LOCAL_MAP_NR(addr) \ (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif #endif diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h index 32d3d5b..8743ff5 100644 --- a/include/asm-arm/arch-sa1100/memory.h +++ b/include/asm-arm/arch-sa1100/memory.h @@ -99,10 +99,6 @@ __arch_adjust_zones(int node, unsigned long *size, unsigned long *holes) #define LOCAL_MAP_NR(addr) \ (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) -#else - -#define PFN_TO_NID(addr) (0) - #endif #endif -- cgit v0.10.2 From 917afce1000d978dfd3f07da5da9d864bc49c77e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 15 Sep 2005 13:00:25 +0100 Subject: [ARM] 2911/1: ixp2000_reg_{read,write} accessors Patch from Lennert Buytenhek This patch: - changes the ixp2000_reg_write accessor to take a 'volatile void *' instead of a 'volatile unsigned long *', which then allows passing in a u32 * as first argument without being greeted with a warning; and - adds an ixp2000_reg_read accessor. We can then use these accessors in ixp2000 code to access on-chip peripherals, instead of directly dereferencing pointers. This is for use by the ixp2000 microengine driver which was recently announced on netdev. We can't use readl/writel on the ixp2000 since it is usually run in big-endian mode, and on big-endian platforms, readl/writel perform byteswapping. A future patch will remove the readback from ixp2000_reg_write, since it's not needed to prevent erratum #66, and add manual readbacks to the places that need them (writes are not synchronous since we map in device space using XCB=101 nowadays), such as interrupt disabling and GPIO manipulation. See also: http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2005-February/027084.html Patch has been ACKed by Jeff Garzik. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index c0caf3e..6519498 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h @@ -31,20 +31,24 @@ #include /* Pickup local_irq_ functions */ -static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val) +static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) { - volatile unsigned long dummy; + unsigned long dummy; unsigned long flags; local_irq_save(flags); - *reg = val; + *((volatile unsigned long *)reg) = val; barrier(); - dummy = *reg; + dummy = *((volatile unsigned long *)reg); local_irq_restore(flags); } #else -#define ixp2000_reg_write(reg, val) (*reg = val) +static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) +{ + *((volatile unsigned long *)reg) = val; +} #endif /* IXDP2400 || IXDP2401 */ +#define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) /* * Boards may multiplex different devices on the 2nd channel of -- cgit v0.10.2 From 44449bbf4b051ef7bbea648602f4e21658fe2354 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 15 Sep 2005 13:00:52 +0100 Subject: [ARM] 2909/1: remove IXP2000_PROD_ID Patch from Lennert Buytenhek The intel docs call it IXP2000_PRODUCT_ID, and we have a definition for IXP2000_PRODUCT_ID as well, so IXP2000_PROD_ID can go. It's only used in one place. Signed-off-by: Lennert Buytenhek Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 75623f8..32aece0 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h @@ -370,8 +370,6 @@ #define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00) #define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x)) -#define IXP2000_PROD_ID GLOBAL_REG(0x00) - #define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000 #define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000 #define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00 diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index 6519498..abdcf51 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h @@ -88,7 +88,7 @@ void ixp2000_release_slowport(struct slowport_cfg *); */ static inline unsigned ixp2000_has_broken_slowport(void) { - unsigned long id = *IXP2000_PROD_ID; + unsigned long id = *IXP2000_PRODUCT_ID; unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK | IXP2000_MIN_PROD_TYPE_MASK); return (((id_prod == -- cgit v0.10.2 From 2e4e8bbb6e2da073c5654a39a58eb0895e3ba4c7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 15 Sep 2005 13:02:31 +0100 Subject: [ARM] 2904/1: update ixp2000 defconfigs to 2.6.13 Patch from Lennert Buytenhek Signed-off-by: Lennert Buytenhek Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index f67ca01..a8c001f 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:41:21 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:51:52 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -135,7 +135,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -179,6 +178,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -248,6 +309,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -334,72 +396,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -509,6 +507,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -649,11 +649,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -679,30 +696,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -770,6 +772,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -812,8 +815,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 5c6c928..5ea356e 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:01 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:01 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -813,8 +816,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 6dc40f6..c542d7f 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:08 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:10 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -814,8 +817,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index d2bb0b7..f4d30e3 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:20 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:23 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -813,8 +816,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index 2d6f960..2612d90 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc2 -# Thu Jul 7 16:49:13 2005 +# Linux kernel version: 2.6.13 +# Wed Sep 14 10:52:16 2005 # CONFIG_ARM=y CONFIG_MMU=y @@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y # # Kernel Features # -# CONFIG_SMP is not set # CONFIG_PREEMPT is not set # CONFIG_NO_IDLE_HZ is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set @@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Device Drivers # @@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP2000=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set @@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +CONFIG_I2C_SENSOR=y # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# Other I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # # Misc devices @@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -814,8 +817,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y -- cgit v0.10.2 From b2b8c6944544319caa22ed8bcb3443153a1a3b4c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Thu, 15 Sep 2005 13:02:32 +0100 Subject: [ARM] 2905/1: enable the ixp2000 i2c bus driver in ixp2000 defconfigs Patch from Lennert Buytenhek It's silly to have I2C enabled in all ixp2000 defconfigs but not to have the ixp2000 bus driver enabled in any of them. This patch enables CONFIG_I2C_IXP2000 for all in-tree ixp2000 boards. Signed-off-by: Lennert Buytenhek Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index a8c001f..30e6444 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig @@ -635,7 +635,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 5ea356e..678720f 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig @@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index c542d7f..38c9a72 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig @@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index f4d30e3..261e234 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig @@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index 2612d90..12ef23d 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig @@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set -# CONFIG_I2C_IXP2000 is not set +CONFIG_I2C_IXP2000=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set -- cgit v0.10.2 From c071760224d8418f65606bd67e755c6a5463ec53 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 15 Sep 2005 14:52:00 +0100 Subject: [ARM] 2915/1: SA1100 Collie: Correct scoop device calls Patch from Richard Purdie This patch adds a missing parameter to the scoop calls made by collie.c Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 8cb6911..25d6a4e 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -111,12 +111,11 @@ static struct mtd_partition collie_partitions[] = { static void collie_set_vpp(int vpp) { - write_scoop_reg(SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); - if (vpp) { - write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); - } else { - write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); - } + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); + if (vpp) + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); + else + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); } static struct flash_platform_data collie_flash_data = { -- cgit v0.10.2 From fdce05bbfe171882adf53ce32e04da24276cb8cd Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 15 Sep 2005 14:53:21 +0100 Subject: [ARM] 2912/1: PXA Corgi: Cleanup some unneeded code Patch from Richard Purdie This patch cleans up the PXA Corgi platform code removing an unneeded static iomap, an unneeded function and some debug messages. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 426c2bc..be37586 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -198,13 +198,10 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - if (( 1 << vdd) & p_d->ocr_mask) { - printk(KERN_DEBUG "%s: on\n", __FUNCTION__); + if (( 1 << vdd) & p_d->ocr_mask) GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); - } else { - printk(KERN_DEBUG "%s: off\n", __FUNCTION__); + else GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); - } } static int corgi_mci_get_ro(struct device *dev) @@ -259,6 +256,16 @@ static struct platform_device *devices[] __initdata = { static void __init corgi_init(void) { + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x0158C000; + PGSR1 = 0x00FF0080; + PGSR2 = 0x0001C004; + /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ + PCFR |= PCFR_OPDE; + corgi_ssp_set_machinfo(&corgi_ssp_machinfo); pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); @@ -285,42 +292,14 @@ static void __init fixup_corgi(struct machine_desc *desc, mi->bank[0].size = (64*1024*1024); } -static void __init corgi_init_irq(void) -{ - pxa_init_irq(); -} - -static struct map_desc corgi_io_desc[] __initdata = { -/* virtual physical length */ -/* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */ -/* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */ - { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ -}; - -static void __init corgi_map_io(void) -{ - pxa_map_io(); - iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc)); - - /* setup sleep mode values */ - PWER = 0x00000002; - PFER = 0x00000000; - PRER = 0x00000002; - PGSR0 = 0x0158C000; - PGSR1 = 0x00FF0080; - PGSR2 = 0x0001C004; - /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ - PCFR |= PCFR_OPDE; -} - #ifdef CONFIG_MACH_CORGI MACHINE_START(CORGI, "SHARP Corgi") .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -332,8 +311,8 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -345,8 +324,8 @@ MACHINE_START(HUSKY, "SHARP Husky") .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, - .map_io = corgi_map_io, - .init_irq = corgi_init_irq, + .map_io = pxa_map_io, + .init_irq = pxa_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END -- cgit v0.10.2 From f29d245549aa38325c37716dbecea8d817c00274 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 15 Sep 2005 14:53:22 +0100 Subject: [ARM] 2913/1: PXA Poodle: Cleanup some unneeded code Patch from Richard Purdie This patch cleans up the PXA Poodle platform code removing an unneeded static iomap. It also corrects errors in the platform header file and adds a missing GPIO define. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 47cfb8b..7c4a1ce 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -126,6 +126,15 @@ static void __init poodle_init(void) { int ret = 0; + /* setup sleep mode values */ + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x00008000; + PGSR1 = 0x003F0202; + PGSR2 = 0x0001C000; + PCFR |= PCFR_OPDE; + /* cpu initialize */ /* Pgsr Register */ PGSR0 = 0x0146dd80; @@ -171,32 +180,12 @@ static void __init fixup_poodle(struct machine_desc *desc, sharpsl_save_param(); } -static struct map_desc poodle_io_desc[] __initdata = { - /* virtual physical length */ - { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ -}; - -static void __init poodle_map_io(void) -{ - pxa_map_io(); - iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc)); - - /* setup sleep mode values */ - PWER = 0x00000002; - PFER = 0x00000000; - PRER = 0x00000002; - PGSR0 = 0x00008000; - PGSR1 = 0x003F0202; - PGSR2 = 0x0001C000; - PCFR |= PCFR_OPDE; -} - MACHINE_START(POODLE, "SHARP Poodle") .phys_ram = 0xa0000000, .phys_io = 0x40000000, .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, - .map_io = poodle_map_io, + .map_io = pxa_map_io, .init_irq = pxa_init_irq, .timer = &pxa_timer, .init_machine = poodle_init, diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h index 58bda9d..6b5ac51 100644 --- a/include/asm-arm/arch-pxa/poodle.h +++ b/include/asm-arm/arch-pxa/poodle.h @@ -37,24 +37,25 @@ #define POODLE_GPIO_nSD_DETECT (9) #define POODLE_GPIO_MAIN_BAT_LOW (13) #define POODLE_GPIO_BAT_COVER (13) +#define POODLE_GPIO_USB_PULLUP (20) #define POODLE_GPIO_ADC_TEMP_ON (21) #define POODLE_GPIO_BYPASS_ON (36) #define POODLE_GPIO_CHRG_ON (38) #define POODLE_GPIO_CHRG_FULL (16) /* PXA GPIOs */ -#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO0 -#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO1 -#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO4 -#define POODLE_IRQ_GPIO_CO IRQ_GPIO16 -#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO5 -#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO11 -#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO10 -#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO17 -#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO14 -#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO8 -#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO9 -#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO13 +#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0) +#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO(1) +#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO(4) +#define POODLE_IRQ_GPIO_CO IRQ_GPIO(16) +#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO(5) +#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO(11) +#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO(10) +#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO(17) +#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO(14) +#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO(8) +#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9) +#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(13) /* SCOOP GPIOs */ #define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11 -- cgit v0.10.2 From 13b9d47ed36e8019a99c798b84c341ef75868e02 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 15 Sep 2005 14:53:22 +0100 Subject: [ARM] 2914/1: PXA Poodle: Add MMC and UDC support Patch from Richard Purdie This patch adds MMC and UDC support to the PXA Poodle platform. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 7c4a1ce..f256388 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include @@ -93,6 +95,83 @@ static struct platform_device locomo_device = { .resource = locomo_resources, }; + +/* + * MMC/SD Device + * + * The card detect interrupt isn't debounced so we delay it by 250ms + * to give the card a chance to fully insert/eject. + */ +static struct pxamci_platform_data poodle_mci_platform_data; + +static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + + /* setup GPIO for PXA25x MMC controller */ + pxa_gpio_mode(GPIO6_MMCCLK_MD); + pxa_gpio_mode(GPIO8_MMCCS0_MD); + pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN); + pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT); + + poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); + + err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + + set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); + + return 0; +} + +static void poodle_mci_setpower(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) + GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR); + else + GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR); +} + +static void poodle_mci_exit(struct device *dev, void *data) +{ + free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data); +} + +static struct pxamci_platform_data poodle_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = poodle_mci_init, + .setpower = poodle_mci_setpower, + .exit = poodle_mci_exit, +}; + + +/* + * USB Device Controller + */ +static void poodle_udc_command(int cmd) +{ + switch(cmd) { + case PXA2XX_UDC_CMD_CONNECT: + GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); + break; + case PXA2XX_UDC_CMD_DISCONNECT: + GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); + break; + } +} + +static struct pxa2xx_udc_mach_info udc_info __initdata = { + /* no connect GPIO; poodle can't tell connection status */ + .udc_command = poodle_udc_command, +}; + + /* PXAFB device */ static struct pxafb_mach_info poodle_fb_info __initdata = { .pixclock = 144700, @@ -164,6 +243,9 @@ static void __init poodle_init(void) GPSR2 = 0x00000000; set_pxa_fb_info(&poodle_fb_info); + pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); + pxa_set_udc_info(&udc_info); + pxa_set_mci_info(&poodle_mci_platform_data); scoop_num = 1; scoop_devs = &poodle_pcmcia_scoop[0]; -- cgit v0.10.2 From b5683557331b129658ab435391df527ef72d63dc Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 15 Sep 2005 08:59:36 -0500 Subject: [SCSI] atp870u: fix memory addressing bug From: Alan Cox The virt_to_bus() wasn't correctly taken out of this driver. It needs to be able to track both physical and virtual addresses for its prd table. Update the driver to do this with separate tracking entries. Signed-off-by: Alan Cox Signed-off-by: James Bottomley diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index e6153fe..a8cfbef 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -996,6 +996,7 @@ oktosend: #ifdef ED_DBGP printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); #endif + dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; outl(dev->id[c][target_id].prdaddr, tmpcip); tmpcip = tmpcip - 2; outb(0x06, tmpcip); @@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host) for (k = 0; k < 16; k++) { if (!atp_dev->id[j][k].prd_table) continue; - pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr); + pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus); atp_dev->id[j][k].prd_table = NULL; } } @@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host) int c,k; for(c=0;c < 2;c++) { for(k=0;k<16;k++) { - atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr)); + atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus)); if (!atp_dev->id[c][k].prd_table) { printk("atp870u_init_tables fail\n"); atp870u_free_tables(host); return -ENOMEM; } + atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; atp_dev->id[c][k].devsp=0x20; atp_dev->id[c][k].devtype = 0x7f; atp_dev->id[c][k].curr_req = NULL; diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h index 89f43af..62bae64 100644 --- a/drivers/scsi/atp870u.h +++ b/drivers/scsi/atp870u.h @@ -54,8 +54,9 @@ struct atp_unit unsigned long tran_len; unsigned long last_len; unsigned char *prd_pos; - unsigned char *prd_table; - dma_addr_t prdaddr; + unsigned char *prd_table; /* Kernel address of PRD table */ + dma_addr_t prd_bus; /* Bus address of PRD */ + dma_addr_t prdaddr; /* Dynamically updated in driver */ struct scsi_cmnd *curr_req; } id[2][16]; struct Scsi_Host *host; -- cgit v0.10.2 From 1b3cb73f7306f97a68fa973dec9f3c3b68bd29cf Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 15 Sep 2005 15:17:59 +0100 Subject: [ARM] Tighten pfn_valid() test. Thomas Gleixner reported that mmaping and unmapping each physical page in turn eventually caused the kernel to oops. It appears that pfn_valid() in the discontigmem case was too simplistic for proper operation. Tighten the logic so we also check if the PFN is within the range of the selected memory node. Signed-off-by: Russell King diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index e47bea7..a8a933a 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h @@ -160,12 +160,25 @@ static inline __deprecated void *bus_to_virt(unsigned long x) #define page_to_pfn(page) \ (( (page) - page_zone(page)->zone_mem_map) \ + page_zone(page)->zone_start_pfn) + #define pfn_to_page(pfn) \ (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) -#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES) + +#define pfn_valid(pfn) \ + ({ \ + unsigned int nid = PFN_TO_NID(pfn); \ + int valid = nid < MAX_NUMNODES; \ + if (valid) { \ + pg_data_t *node = NODE_DATA(nid); \ + valid = (pfn - node->node_start_pfn) < \ + node->node_spanned_pages; \ + } \ + valid; \ + }) #define virt_to_page(kaddr) \ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) + #define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES) /* -- cgit v0.10.2 From be201f7f4cd26b1bb994062803e0d87877e749ce Mon Sep 17 00:00:00 2001 From: Jimi Xenidis Date: Thu, 15 Sep 2005 08:42:19 -0400 Subject: [PATCH] ppc64: Fix recent regression As noted by Olof Johansson : "A recent patch changed the way the LPAR bit is checked during early boot. This resulted in a polarity change in a conditional branch without changing the branch, causing at least some legacy machines to not boot." This fixes it. Signed-off-by: Jimi Xenidis Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 58c3147..72c6104 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -1649,7 +1649,7 @@ _GLOBAL(__secondary_start) ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ - bne 98f + beq 98f /* branch if result is 0 */ mfspr r3,PVR srwi r3,r3,16 cmpwi r3,0x37 /* SStar */ @@ -1813,7 +1813,7 @@ _STATIC(start_here_multiplatform) ld r3,0(r3) lwz r3,PLATFORM(r3) /* r3 = platform flags */ andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ - bne 98f + beq 98f /* branch if result is 0 */ mfspr r3,PVR srwi r3,r3,16 cmpwi r3,0x37 /* SStar */ @@ -1834,7 +1834,7 @@ _STATIC(start_here_multiplatform) lwz r3,PLATFORM(r3) /* r3 = platform flags */ /* Test if bit 0 is set (LPAR bit) */ andi. r3,r3,PLATFORM_LPAR - bne 98f + bne 98f /* branch if result is !0 */ LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 ld r6,0(r6) /* get the value of _SDR1 */ -- cgit v0.10.2 From 7b6a186d65589901a73d460070504a5e02703c45 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Thu, 15 Sep 2005 20:58:57 +0800 Subject: [PATCH] savagefb: Fix load failure of the Twister chipset - The Twister chipsets are actually prosavages. Reclassify them as such and remove the S3_SAVAGE_TWISTER id. - Fix i2c code if fb_firmware_edid() returns NULL Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 959404a..3c98457 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c @@ -274,10 +274,13 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) if (!edid) { /* try to get from firmware */ - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, fb_firmware_edid(info->device), - EDID_LENGTH); + const u8 *e = fb_firmware_edid(info->device); + + if (e) { + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (edid) + memcpy(edid, e, EDID_LENGTH); + } } if (out_edid) diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index d6f9474..ea17f7e 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h @@ -60,8 +60,6 @@ #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) -#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR)) - /* Chip tags. These are used to group the adapters into * related families. */ @@ -74,8 +72,6 @@ typedef enum { S3_PROSAVAGE, S3_SUPERSAVAGE, S3_SAVAGE2000, - S3_PROSAVAGEDDR, - S3_TWISTER, S3_LAST } savage_chipset; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index b5ca3ef..7c28545 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1773,8 +1773,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) } } - if (S3_SAVAGE_MOBILE_SERIES(par->chip) || - (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly)) + if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly) par->display_type = DISP_LCD; else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) par->display_type = DISP_DFP; @@ -1783,7 +1782,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) /* Check LCD panel parrmation */ - if (par->chip == S3_SAVAGE_MX) { + if (par->display_type == DISP_LCD) { unsigned char cr6b = VGArCR( 0x6b ); int panelX = (VGArSEQ (0x61) + @@ -1922,15 +1921,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info, snprintf (info->fix.id, 16, "ProSavageKM"); break; case FB_ACCEL_S3TWISTER_P: - par->chip = S3_TWISTER; + par->chip = S3_PROSAVAGE; snprintf (info->fix.id, 16, "TwisterP"); break; case FB_ACCEL_S3TWISTER_K: - par->chip = S3_TWISTER; + par->chip = S3_PROSAVAGE; snprintf (info->fix.id, 16, "TwisterK"); break; case FB_ACCEL_PROSAVAGE_DDR: - par->chip = S3_PROSAVAGEDDR; + par->chip = S3_PROSAVAGE; snprintf (info->fix.id, 16, "ProSavageDDR"); break; case FB_ACCEL_PROSAVAGE_DDRK: -- cgit v0.10.2 From 6d36ba629e0ef47a03d3703ee1d38143c25532a8 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Thu, 15 Sep 2005 21:14:56 +0800 Subject: [PATCH] vgacon: Fix sanity checking in vgacon_resize Reported by: walt "I routinely switch the console font during bootup to 8x8 so I can get 50 lines per screen. Until 09 Sept, just changing to the small font automatically gave me all 50 lines -- but now I'm only getting 25 lines even with the small font. The bottom half of the screen displays the text that already scrolled off the top." This bug is due to an erroneous check in the recently added hook, vgacon_resize(). It checks the new height against the original number of rows of the console. Because the original number of rows depends on both the scanline and the font height, check it instead against the scanline/fontheight. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0705cd7..6ef6f77 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1020,7 +1020,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) static int vgacon_resize(struct vc_data *c, unsigned int width, unsigned int height) { - if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES) + if (width % 2 || width > ORIG_VIDEO_COLS || + height > (ORIG_VIDEO_LINES * vga_default_font_height)/ + c->vc_font.height) return -EINVAL; if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ -- cgit v0.10.2 From 065d9cac98a5406ecd5a1368f8fd38f55739dee9 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Thu, 15 Sep 2005 21:34:33 +0800 Subject: [PATCH] vc: Use correct size on buffer copy in vc_resize In the unlikely case of the new screen width much wider then the old, use (old_row_size * new_rows) instead of new_screen_size to prevent a buffer overrun during the copy. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1e33cb0..e91268e 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -810,13 +810,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) * from the top and bottom of cursor position */ old_origin += (vc->vc_y - new_rows/2) * old_row_size; - end = old_origin + new_screen_size; + end = old_origin + (old_row_size * new_rows); } } else /* * Cursor near the top, copy contents from the top of buffer */ - end = (old_rows > new_rows) ? old_origin + new_screen_size : + end = (old_rows > new_rows) ? old_origin + + (old_row_size * new_rows) : vc->vc_scr_end; update_attr(vc); -- cgit v0.10.2 From 541950027f8b7c96a639bc16e48930c590f1b98a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 15 Sep 2005 21:52:51 -0400 Subject: [SCSI] fix use after potential free in scsi_remove_device Signed-off-by: Alan Stern Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b8052d5..83f87c4 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -707,9 +707,11 @@ void __scsi_remove_device(struct scsi_device *sdev) **/ void scsi_remove_device(struct scsi_device *sdev) { - down(&sdev->host->scan_mutex); + struct Scsi_Host *shost = sdev->host; + + down(&shost->scan_mutex); __scsi_remove_device(sdev); - up(&sdev->host->scan_mutex); + up(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_remove_device); -- cgit v0.10.2 From 6cb1269b9607649b5edf1c4e7818e0cf34a9db71 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Thu, 15 Sep 2005 23:25:41 -0500 Subject: JFS: Fix sparse warnings, including endian error The fix in inode.c is a real bug. It could result in undeleted, yet unconnected files on big-endian hardware. The others are trivial. Signed-off-by: Dave Kleikamp diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 0ec62d5..9f942ca 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -129,8 +129,7 @@ void jfs_delete_inode(struct inode *inode) jfs_info("In jfs_delete_inode, inode = 0x%p", inode); if (!is_bad_inode(inode) && - (JFS_IP(inode)->fileset == cpu_to_le32(FILESYSTEM_I))) { - + (JFS_IP(inode)->fileset == FILESYSTEM_I)) { truncate_inode_pages(&inode->i_data, 0); if (test_cflag(COMMIT_Freewmap, inode)) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index c739626..eadf319 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -3055,7 +3055,7 @@ static int cntlz(u32 value) * RETURN VALUES: * log2 number of blocks */ -int blkstol2(s64 nb) +static int blkstol2(s64 nb) { int l2nb; s64 mask; /* meant to be signed */ diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index c7a92f9..8132fce 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -2070,8 +2070,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * * function: log from maplock of freed data extents; */ -void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, - struct tlock * tlck) +static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, + struct tlock * tlck) { struct pxd_lock *pxdlock; int i, nlock; @@ -2209,7 +2209,7 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea) * function: synchronously write pages locked by transaction * after txLog() but before txUpdateMap(); */ -void txForce(struct tblock * tblk) +static void txForce(struct tblock * tblk) { struct tlock *tlck; lid_t lid, next; -- cgit v0.10.2 From 7a83e90b32a2b2500e0be6a5317ab411b39222c9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 15 Sep 2005 15:24:59 +0100 Subject: [PATCH] PATCH: silly in piix driver Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 87e0c36..d71cef7 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -442,7 +442,6 @@ static void piix_sata_phy_reset(struct ata_port *ap) * piix_set_piomode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring * @adev: um - * @pio: PIO mode, 0 - 4 * * Set PIO mode for device, in host controller PCI config space. * -- cgit v0.10.2 From 17b14451fd2b187ddd6303726755a3af0a926b6c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 15 Sep 2005 15:44:00 +0100 Subject: [PATCH] PATCH: remove function for non-PCI as requested Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5cc53cd..72bdc91 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4123,6 +4123,53 @@ err_out: } /** + * ata_host_set_remove - PCI layer callback for device removal + * @host_set: ATA host set that was removed + * + * Unregister all objects associated with this host set. Free those + * objects. + * + * LOCKING: + * Inherited from calling layer (may sleep). + */ + + +void ata_host_set_remove(struct ata_host_set *host_set) +{ + struct ata_port *ap; + unsigned int i; + + for (i = 0; i < host_set->n_ports; i++) { + ap = host_set->ports[i]; + scsi_remove_host(ap->host); + } + + free_irq(host_set->irq, host_set); + + for (i = 0; i < host_set->n_ports; i++) { + ap = host_set->ports[i]; + + ata_scsi_release(ap->host); + + if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { + struct ata_ioports *ioaddr = &ap->ioaddr; + + if (ioaddr->cmd_addr == 0x1f0) + release_region(0x1f0, 8); + else if (ioaddr->cmd_addr == 0x170) + release_region(0x170, 8); + } + + scsi_host_put(ap->host); + } + + if (host_set->ops->host_stop) + host_set->ops->host_stop(host_set); + + kfree(host_set); +} + +/** * ata_scsi_release - SCSI layer callback hook for host unload * @host: libata host to be unloaded * @@ -4462,39 +4509,8 @@ void ata_pci_remove_one (struct pci_dev *pdev) { struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); - struct ata_port *ap; - unsigned int i; - - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - - scsi_remove_host(ap->host); - } - - free_irq(host_set->irq, host_set); - - for (i = 0; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - - ata_scsi_release(ap->host); - - if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { - struct ata_ioports *ioaddr = &ap->ioaddr; - - if (ioaddr->cmd_addr == 0x1f0) - release_region(0x1f0, 8); - else if (ioaddr->cmd_addr == 0x170) - release_region(0x170, 8); - } - - scsi_host_put(ap->host); - } - - if (host_set->ops->host_stop) - host_set->ops->host_stop(host_set); - - kfree(host_set); + ata_host_set_remove(host_set); pci_release_regions(pdev); pci_disable_device(pdev); dev_set_drvdata(dev, NULL); @@ -4564,6 +4580,7 @@ module_exit(ata_exit); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); EXPORT_SYMBOL_GPL(ata_device_add); +EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_qc_complete); diff --git a/include/linux/libata.h b/include/linux/libata.h index 022105c..ceee1fc 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -393,6 +393,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i extern void ata_pci_remove_one (struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(struct ata_probe_ent *ent); +extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(Scsi_Host_Template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -- cgit v0.10.2 From ed4b9f8014db4f343e89b44b7c5ca355f439ce36 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Wed, 14 Sep 2005 14:52:09 -0700 Subject: [PATCH] bonding: plug reference count leak Bonding leaks route structures when the ARP monitor is configured to send probes over VLANs. Originally reported by Ian Abel ; his original fix was modified by Jay Vosburgh to correct coding style and to close a leak it missed. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94c9f68..f8dedb6 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) * This target is not on a VLAN */ if (rt->u.dst.dev == bond->dev) { + ip_rt_put(rt); dprintk("basa: rtdev == bond->dev: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], bond->master_ip, 0); @@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) } if (vlan_id) { + ip_rt_put(rt); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], vlan->vlan_ip, vlan_id); continue; @@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) bond->dev->name, NIPQUAD(fl.fl4_dst), rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); } + ip_rt_put(rt); } } -- cgit v0.10.2 From 8b51292764a0ed46d7eb6bead4625ba83ee2ec05 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 14 Sep 2005 09:45:44 -0700 Subject: [PATCH] 8139cp: allocate statistics space only when needed Don't crash if ethtool statistics are requested and device is down. Fix is to allocate pci space for statistics only when needed. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 34b80de..bc53744 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -353,8 +353,6 @@ struct cp_private { struct net_device_stats net_stats; struct cp_extra_stats cp_stats; - struct cp_dma_stats *nic_stats; - dma_addr_t nic_stats_dma; unsigned rx_tail ____cacheline_aligned; struct cp_desc *rx_ring; @@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp) cp->rx_ring = mem; cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; - mem += (CP_RING_BYTES - CP_STATS_SIZE); - cp->nic_stats = mem; - cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); - return cp_init_rings(cp); } @@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp) pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); cp->rx_ring = NULL; cp->tx_ring = NULL; - cp->nic_stats = NULL; } static int cp_open (struct net_device *dev) @@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { struct cp_private *cp = netdev_priv(dev); + struct cp_dma_stats *nic_stats; + dma_addr_t dma; int i; - memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); + nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); + if (!nic_stats) + return; /* begin NIC statistics dump */ - cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); - cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); + cpw32(StatsAddr + 4, (u64)dma >> 32); + cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); cpr32(StatsAddr); for (i = 0; i < 1000; i++) { @@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev, } cpw32(StatsAddr, 0); cpw32(StatsAddr + 4, 0); + cpr32(StatsAddr); i = 0; - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); - tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); - tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); - tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); + tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); + tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); + tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); + tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); + tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); + tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); + tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); + tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); + tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); + tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); + tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); tmp_stats[i++] = cp->cp_stats.rx_frags; if (i != CP_NUM_STATS) BUG(); + + pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); } static struct ethtool_ops cp_ethtool_ops = { -- cgit v0.10.2 From 53abbf7eeab22620586cbba272e569fd3e729b0b Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Fri, 16 Sep 2005 08:55:33 +0200 Subject: [PATCH] net: fix spider_net media detection This patch makes the driver work with any BladeCenter network switch, it used to work only with certain models. Please apply. Signed-off-by: Arnd Bergmann Signed-off-by: Jeff Garzik diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 4e19220..c796f41 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card) /* LEDs active in both modes, autosense prio = fiber */ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); + /* switch off fibre autoneg */ + spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); + spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); + phy->def->ops->read_link(phy); pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half"); -- cgit v0.10.2 From 7fb6ec287a05d7a71ec086d8bc9a452d5e16ff1a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 16 Sep 2005 06:01:48 -0400 Subject: [libata] fix PIO completion race Make sure we that completion is the final action we take; prior to this change, another CPU may have changed ap->pio_task_state before we tested it a final time. Spotted by, and original patch by Albert Lee @ IBM. Also includes a minor optimization: eliminate a ton of unnecessary queue_work() calls, simply by jumping to the beginning of the FSM function ata_pio_task(). diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5cc53cd..d92273c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap) * * LOCKING: * None. (executing in kernel thread context) + * + * RETURNS: + * Non-zero if qc completed, zero otherwise. */ -static void ata_pio_complete (struct ata_port *ap) +static int ata_pio_complete (struct ata_port *ap) { struct ata_queued_cmd *qc; u8 drv_stat; @@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap) if (drv_stat & (ATA_BUSY | ATA_DRQ)) { ap->pio_task_state = PIO_ST_LAST_POLL; ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; - return; + return 0; } } drv_stat = ata_wait_idle(ap); if (!ata_ok(drv_stat)) { ap->pio_task_state = PIO_ST_ERR; - return; + return 0; } qc = ata_qc_from_tag(ap, ap->active_tag); @@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap) ap->pio_task_state = PIO_ST_IDLE; ata_poll_qc_complete(qc, drv_stat); + + /* another command may start at this point */ + + return 1; } @@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) next_sg: if (unlikely(qc->cursg >= qc->n_elem)) { - /* + /* * The end of qc->sg is reached and the device expects * more data to transfer. In order not to overrun qc->sg * and fulfill length specified in the byte count register, @@ -2721,7 +2728,7 @@ next_sg: unsigned int i; if (words) /* warning if bytes > 1 */ - printk(KERN_WARNING "ata%u: %u bytes trailing data\n", + printk(KERN_WARNING "ata%u: %u bytes trailing data\n", ap->id, bytes); for (i = 0; i < words; i++) @@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap) if (is_atapi_taskfile(&qc->tf)) { /* no more data to transfer or unsupported ATAPI command */ if ((status & ATA_DRQ) == 0) { - ap->pio_task_state = PIO_ST_IDLE; - - ata_poll_qc_complete(qc, status); + ap->pio_task_state = PIO_ST_LAST; return; } @@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap) static void ata_pio_task(void *_data) { struct ata_port *ap = _data; - unsigned long timeout = 0; + unsigned long timeout; + int qc_completed; + +fsm_start: + timeout = 0; + qc_completed = 0; switch (ap->pio_task_state) { case PIO_ST_IDLE: @@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data) break; case PIO_ST_LAST: - ata_pio_complete(ap); + qc_completed = ata_pio_complete(ap); break; case PIO_ST_POLL: @@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data) } if (timeout) - queue_delayed_work(ata_wq, &ap->pio_task, - timeout); - else - queue_work(ata_wq, &ap->pio_task); + queue_delayed_work(ata_wq, &ap->pio_task, timeout); + else if (!qc_completed) + goto fsm_start; } static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, -- cgit v0.10.2 From 1832a5862f2e1b4e5835611ee14bc30a8ed3cad5 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 16 Sep 2005 11:01:14 +0200 Subject: [SCSI] change port speed definitions for scsi_transport_fc obviously FC Port Speeds in scsi_transport_fc.h are defined according to FC-HBA: #define FC_PORTSPEED_1GBIT 1 #define FC_PORTSPEED_2GBIT 2 #define FC_PORTSPEED_10GBIT 4 #define FC_PORTSPEED_4GBIT 8 Problem is, whoever invented FC-HBA did not care about FC-FS or FC-GS-x. Following FC-FS/FC-GS-x defintions of port speeds would look like: 1 GBit: 0x0001 2 GBit: 0x0002 4 GBit: 0x0004 10GBit: 0x0008 (and new in FC-LS: 8 Gbit: 0x0010 16GBit: 0x0020) I really appreciate if scsi_transport_fc.h would define port speeds according to FC-GS-x/FC-FS. Thus mapping of port speed capabilities to values defined in scsi_transport_fc.h can be avoided in the LLDD. Attached is a patch to change the definitions. Signed-off-by: James Bottomley diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 115db05..b0d4454 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -103,8 +103,8 @@ enum fc_port_state { incapable of reporting */ #define FC_PORTSPEED_1GBIT 1 #define FC_PORTSPEED_2GBIT 2 -#define FC_PORTSPEED_10GBIT 4 -#define FC_PORTSPEED_4GBIT 8 +#define FC_PORTSPEED_4GBIT 4 +#define FC_PORTSPEED_10GBIT 8 #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ /* -- cgit v0.10.2 From 24b8e0cc09483adc0fdd9c68914b19597bb9fddc Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Thu, 15 Sep 2005 15:36:35 +1000 Subject: [IA64] Remove warnings for gcc 4.0 IA64 compilation. This patch removes some compilation warnings, mostly trivially. acpi.c fix also noted by Kenji Kaneshige. Signed-off-by; Peter Chubb Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 28a4529..7e92647 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) if ((err = iosapic_init(phys_addr, gsi_base))) return err; -#if CONFIG_ACPI_NUMA +#ifdef CONFIG_ACPI_NUMA acpi_map_iosapic(handle, 0, NULL, NULL); #endif /* CONFIG_ACPI_NUMA */ diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ba0b6a1..0741b066 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack) ;; lfetch.fault [r16], 128 br.ret.sptk.many rp -END(prefetch_switch_stack) +END(prefetch_stack) GLOBAL_ENTRY(execve) mov r15=__NR_execve // put syscall number in place diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 1650353..af42cda 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x) return 0UL; } -static inline unsigned long +static inline void pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) { spin_unlock(&(x)->ctx_lock); diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 99762b6..de5d6d2 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -252,7 +252,7 @@ hp_zx1_configure (void) readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); readl(hp->ioc_regs+HP_ZX1_TCNFG); - writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK); + writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); readl(hp->ioc_regs+HP_ZX1_IMASK); writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); readl(hp->ioc_regs+HP_ZX1_IBASE); -- cgit v0.10.2 From 8ee9e23d41d2c51fafd158861fa4639fb199baf0 Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Fri, 16 Sep 2005 14:49:14 +1000 Subject: [IA64] Add Documentation/ia64/mca.txt Add Documentation/ia64/mca.txt, an ad-hoc collection of notes on IA64 MCA and INIT processing. Signed-off-by: Keith Owens Signed-off-by: Tony Luck diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt new file mode 100644 index 0000000..a71cc6a --- /dev/null +++ b/Documentation/ia64/mca.txt @@ -0,0 +1,194 @@ +An ad-hoc collection of notes on IA64 MCA and INIT processing. Feel +free to update it with notes about any area that is not clear. + +--- + +MCA/INIT are completely asynchronous. They can occur at any time, when +the OS is in any state. Including when one of the cpus is already +holding a spinlock. Trying to get any lock from MCA/INIT state is +asking for deadlock. Also the state of structures that are protected +by locks is indeterminate, including linked lists. + +--- + +The complicated ia64 MCA process. All of this is mandated by Intel's +specification for ia64 SAL, error recovery and and unwind, it is not as +if we have a choice here. + +* MCA occurs on one cpu, usually due to a double bit memory error. + This is the monarch cpu. + +* SAL sends an MCA rendezvous interrupt (which is a normal interrupt) + to all the other cpus, the slaves. + +* Slave cpus that receive the MCA interrupt call down into SAL, they + end up spinning disabled while the MCA is being serviced. + +* If any slave cpu was already spinning disabled when the MCA occurred + then it cannot service the MCA interrupt. SAL waits ~20 seconds then + sends an unmaskable INIT event to the slave cpus that have not + already rendezvoused. + +* Because MCA/INIT can be delivered at any time, including when the cpu + is down in PAL in physical mode, the registers at the time of the + event are _completely_ undefined. In particular the MCA/INIT + handlers cannot rely on the thread pointer, PAL physical mode can + (and does) modify TP. It is allowed to do that as long as it resets + TP on return. However MCA/INIT events expose us to these PAL + internal TP changes. Hence curr_task(). + +* If an MCA/INIT event occurs while the kernel was running (not user + space) and the kernel has called PAL then the MCA/INIT handler cannot + assume that the kernel stack is in a fit state to be used. Mainly + because PAL may or may not maintain the stack pointer internally. + Because the MCA/INIT handlers cannot trust the kernel stack, they + have to use their own, per-cpu stacks. The MCA/INIT stacks are + preformatted with just enough task state to let the relevant handlers + do their job. + +* Unlike most other architectures, the ia64 struct task is embedded in + the kernel stack[1]. So switching to a new kernel stack means that + we switch to a new task as well. Because various bits of the kernel + assume that current points into the struct task, switching to a new + stack also means a new value for current. + +* Once all slaves have rendezvoused and are spinning disabled, the + monarch is entered. The monarch now tries to diagnose the problem + and decide if it can recover or not. + +* Part of the monarch's job is to look at the state of all the other + tasks. The only way to do that on ia64 is to call the unwinder, + as mandated by Intel. + +* The starting point for the unwind depends on whether a task is + running or not. That is, whether it is on a cpu or is blocked. The + monarch has to determine whether or not a task is on a cpu before it + knows how to start unwinding it. The tasks that received an MCA or + INIT event are no longer running, they have been converted to blocked + tasks. But (and its a big but), the cpus that received the MCA + rendezvous interrupt are still running on their normal kernel stacks! + +* To distinguish between these two cases, the monarch must know which + tasks are on a cpu and which are not. Hence each slave cpu that + switches to an MCA/INIT stack, registers its new stack using + set_curr_task(), so the monarch can tell that the _original_ task is + no longer running on that cpu. That gives us a decent chance of + getting a valid backtrace of the _original_ task. + +* MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a + nested error, we want diagnostics on the MCA/INIT handler that + failed, not on the task that was originally running. Again this + requires set_curr_task() so the MCA/INIT handlers can register their + own stack as running on that cpu. Then a recursive error gets a + trace of the failing handler's "task". + +[1] My (Keith Owens) original design called for ia64 to separate its + struct task and the kernel stacks. Then the MCA/INIT data would be + chained stacks like i386 interrupt stacks. But that required + radical surgery on the rest of ia64, plus extra hard wired TLB + entries with its associated performance degradation. David + Mosberger vetoed that approach. Which meant that separate kernel + stacks meant separate "tasks" for the MCA/INIT handlers. + +--- + +INIT is less complicated than MCA. Pressing the nmi button or using +the equivalent command on the management console sends INIT to all +cpus. SAL picks one one of the cpus as the monarch and the rest are +slaves. All the OS INIT handlers are entered at approximately the same +time. The OS monarch prints the state of all tasks and returns, after +which the slaves return and the system resumes. + +At least that is what is supposed to happen. Alas there are broken +versions of SAL out there. Some drive all the cpus as monarchs. Some +drive them all as slaves. Some drive one cpu as monarch, wait for that +cpu to return from the OS then drive the rest as slaves. Some versions +of SAL cannot even cope with returning from the OS, they spin inside +SAL on resume. The OS INIT code has workarounds for some of these +broken SAL symptoms, but some simply cannot be fixed from the OS side. + +--- + +The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer +violations. Unfortunately MCA/INIT start off as massive layer +violations (can occur at _any_ time) and they build from there. + +At least ia64 makes an attempt at recovering from hardware errors, but +it is a difficult problem because of the asynchronous nature of these +errors. When processing an unmaskable interrupt we sometimes need +special code to cope with our inability to take any locks. + +--- + +How is ia64 MCA/INIT different from x86 NMI? + +* x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to + all cpus. + +* x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2 + per cpu. + +* x86 has a separate struct task which points to one of multiple kernel + stacks. ia64 has the struct task embedded in the single kernel + stack, so switching stack means switching task. + +* x86 does not call the BIOS so the NMI handler does not have to worry + about any registers having changed. MCA/INIT can occur while the cpu + is in PAL in physical mode, with undefined registers and an undefined + kernel stack. + +* i386 backtrace is not very sensitive to whether a process is running + or not. ia64 unwind is very, very sensitive to whether a process is + running or not. + +--- + +What happens when MCA/INIT is delivered what a cpu is running user +space code? + +The user mode registers are stored in the RSE area of the MCA/INIT on +entry to the OS and are restored from there on return to SAL, so user +mode registers are preserved across a recoverable MCA/INIT. Since the +OS has no idea what unwind data is available for the user space stack, +MCA/INIT never tries to backtrace user space. Which means that the OS +does not bother making the user space process look like a blocked task, +i.e. the OS does not copy pt_regs and switch_stack to the user space +stack. Also the OS has no idea how big the user space RSE and memory +stacks are, which makes it too risky to copy the saved state to a user +mode stack. + +--- + +How do we get a backtrace on the tasks that were running when MCA/INIT +was delivered? + +mca.c:::ia64_mca_modify_original_stack(). That identifies and +verifies the original kernel stack, copies the dirty registers from +the MCA/INIT stack's RSE to the original stack's RSE, copies the +skeleton struct pt_regs and switch_stack to the original stack, fills +in the skeleton structures from the PAL minstate area and updates the +original stack's thread.ksp. That makes the original stack look +exactly like any other blocked task, i.e. it now appears to be +sleeping. To get a backtrace, just start with thread.ksp for the +original task and unwind like any other sleeping task. + +--- + +How do we identify the tasks that were running when MCA/INIT was +delivered? + +If the previous task has been verified and converted to a blocked +state, then sos->prev_task on the MCA/INIT stack is updated to point to +the previous task. You can look at that field in dumps or debuggers. +To help distinguish between the handler and the original tasks, +handlers have _TIF_MCA_INIT set in thread_info.flags. + +The sos data is always in the MCA/INIT handler stack, at offset +MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it +as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct +ia64_sal_os_state), with 16 byte alignment for all structures. + +Also the comm field of the MCA/INIT task is modified to include the pid +of the original task, for humans to use. For example, a comm field of +'MCA 12159' means that pid 12159 was running when the MCA was +delivered. -- cgit v0.10.2 From bc9a5154a24d16d41cc79dbf1442de34454bc7db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 15 Sep 2005 22:53:28 +0100 Subject: [PATCH] epca iomem annotations + several missing readw() [originally sent to Alan, he had no problems with it] - iomem pointers marked as such - several direct dereferencings of such pointers replaced with read[bw](). Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 58d3738..407708a 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -534,7 +534,7 @@ static void shutdown(struct channel *ch) unsigned long flags; struct tty_struct *tty; - struct board_chan *bc; + struct board_chan __iomem *bc; if (!(ch->asyncflags & ASYNC_INITIALIZED)) return; @@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty, struct channel *ch; unsigned long flags; int remain; - struct board_chan *bc; + struct board_chan __iomem *bc; /* ---------------------------------------------------------------- pc_write is primarily called directly by the kernel routine @@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty, ------------------------------------------------------------------- */ dataLen = min(bytesAvailable, dataLen); - memcpy(ch->txptr + head, buf, dataLen); + memcpy_toio(ch->txptr + head, buf, dataLen); buf += dataLen; head += dataLen; amountCopied += dataLen; @@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) struct channel *ch; unsigned long flags; unsigned int head, tail; - struct board_chan *bc; + struct board_chan __iomem *bc; remain = 0; @@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) int remain; unsigned long flags; struct channel *ch; - struct board_chan *bc; + struct board_chan __iomem *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct @@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty) unsigned int tail; unsigned long flags; struct channel *ch; - struct board_chan *bc; + struct board_chan __iomem *bc; /* --------------------------------------------------------- verifyChannel returns the channel from the tty struct if it is valid. This serves as a sanity check. @@ -976,7 +976,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) struct channel *ch; unsigned long flags; int line, retval, boardnum; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int head; line = tty->index; @@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) ch->statusflags = 0; /* Save boards current modem status */ - ch->imodem = bc->mstat; + ch->imodem = readb(&bc->mstat); /* ---------------------------------------------------------------- Set receive head and tail ptrs to each other. This indicates @@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd) { /* Begin post_fep_init */ int i; - unsigned char *memaddr; - struct global_data *gd; + void __iomem *memaddr; + struct global_data __iomem *gd; struct board_info *bd; - struct board_chan *bc; + struct board_chan __iomem *bc; struct channel *ch; int shrinkmem = 0, lowwater ; @@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd) 8 and 64 of these structures. -------------------------------------------------------------------- */ - bc = (struct board_chan *)(memaddr + CHANSTRUCT); + bc = memaddr + CHANSTRUCT; /* ------------------------------------------------------------------- The below assignment will set gd to point at the BEGINING of @@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd) pointer begins at 0xd10. ---------------------------------------------------------------------- */ - gd = (struct global_data *)(memaddr + GLOBAL); + gd = memaddr + GLOBAL; /* -------------------------------------------------------------------- XEPORTS (address 0xc22) points at the number of channels the @@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd) for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ unsigned long flags; + u16 tseg, rseg; ch->brdchan = bc; ch->mailbox = gd; @@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd) shrinkmem = 0; } + tseg = readw(&bc->tseg); + rseg = readw(&bc->rseg); + switch (bd->type) { case PCIXEM: case PCIXRJ: case PCIXR: /* Cover all the 2MEG cards */ - ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff); - ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff); - ch->txwin = FEPWIN | ((bc->tseg) >> 11); - ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); + ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); break; case PCXEM: case EISAXEM: /* Cover all the 32K windowed cards */ /* Mask equal to window size - 1 */ - ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff); - ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff); - ch->txwin = FEPWIN | ((bc->tseg) >> 11); - ch->rxwin = FEPWIN | ((bc->rseg) >> 11); + ch->txptr = memaddr + ((tseg << 4) & 0x7fff); + ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); + ch->txwin = FEPWIN | (tseg >> 11); + ch->rxwin = FEPWIN | (rseg >> 11); break; case PCXEVE: case PCXE: - ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff); - ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9); - ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff); - ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 ); + ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); + ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); + ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); + ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 ); break; case PCXI: case PC64XE: - ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4); - ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4); + ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); + ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); ch->txwin = ch->rxwin = 0; break; } /* End switch bd->type */ ch->txbufhead = 0; - ch->txbufsize = bc->tmax + 1; + ch->txbufsize = readw(&bc->tmax) + 1; ch->rxbufhead = 0; - ch->rxbufsize = bc->rmax + 1; + ch->rxbufsize = readw(&bc->rmax) + 1; lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); @@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored) static void doevent(int crd) { /* Begin doevent */ - void *eventbuf; + void __iomem *eventbuf; struct channel *ch, *chan0; static struct tty_struct *tty; struct board_info *bd; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int tail, head; int event, channel; int mstat, lstat; @@ -1817,7 +1821,7 @@ static void doevent(int crd) static void fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds, int bytecmd) { /* Begin fepcmd */ - unchar *memaddr; + unchar __iomem *memaddr; unsigned int head, cmdTail, cmdStart, cmdMax; long count; int n; @@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) unsigned int cmdHead; struct termios *ts; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned mval, hflow, cflag, iflag; bc = ch->brdchan; @@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) ts = tty->termios; if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ cmdHead = readw(&bc->rin); - bc->rout = cmdHead; + writew(cmdHead, &bc->rout); cmdHead = readw(&bc->tin); /* Changing baud in mid-stream transmission can be wonderful */ /* --------------------------------------------------------------- @@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch) unchar *rptr; struct termios *ts = NULL; struct tty_struct *tty; - struct board_chan *bc; + struct board_chan __iomem *bc; int dataToRead, wrapgap, bytesAvailable; unsigned int tail, head; unsigned int wrapmask; @@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch) --------------------------------------------------------------------- */ if (!tty || !ts || !(ts->c_cflag & CREAD)) { - bc->rout = head; + writew(head, &bc->rout); return; } @@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, static int pc_tiocmget(struct tty_struct *tty, struct file *file) { struct channel *ch = (struct channel *) tty->driver_data; - struct board_chan *bc; + struct board_chan __iomem *bc; unsigned int mstat, mflag = 0; unsigned long flags; @@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, unsigned long flags; unsigned int mflag, mstat; unsigned char startc, stopc; - struct board_chan *bc; + struct board_chan __iomem *bc; struct channel *ch = (struct channel *) tty->driver_data; void __user *argp = (void __user *)arg; @@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty) spin_lock_irqsave(&epca_lock, flags); /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ - struct board_chan *bc; + struct board_chan __iomem *bc; globalwinon(ch); bc = ch->brdchan; if (ch->statusflags & LOWWAIT) @@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec) static void setup_empty_event(struct tty_struct *tty, struct channel *ch) { /* Begin setup_empty_event */ - struct board_chan *bc = ch->brdchan; + struct board_chan __iomem *bc = ch->brdchan; globalwinon(ch); ch->statusflags |= EMPTYWAIT; diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 20eeb5a..456d6c8 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h @@ -128,17 +128,17 @@ struct channel unsigned long c_cflag; unsigned long c_lflag; unsigned long c_oflag; - unsigned char *txptr; - unsigned char *rxptr; + unsigned char __iomem *txptr; + unsigned char __iomem *rxptr; unsigned char *tmp_buf; struct board_info *board; - struct board_chan *brdchan; + struct board_chan __iomem *brdchan; struct digi_struct digiext; struct tty_struct *tty; wait_queue_head_t open_wait; wait_queue_head_t close_wait; struct work_struct tqueue; - struct global_data *mailbox; + struct global_data __iomem *mailbox; }; struct board_info @@ -149,8 +149,8 @@ struct board_info unsigned short numports; unsigned long port; unsigned long membase; - unsigned char __iomem *re_map_port; - unsigned char *re_map_membase; + void __iomem *re_map_port; + void __iomem *re_map_membase; unsigned long memory_seg; void ( * memwinon ) (struct board_info *, unsigned int) ; void ( * memwinoff ) (struct board_info *, unsigned int) ; -- cgit v0.10.2 From 20305e59724381365096b6ab0a48054723367c80 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Fri, 16 Sep 2005 13:44:56 +0900 Subject: [IA64] mca_drv cleanup There were some trailing white spaces, long lines, brackets in weird style etc. This patch cleans them up. Signed-off-by: Hidetoshi Seto Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 6e68374..80f83d6 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr) struct page *p; /* whether physical address is valid or not */ - if ( !ia64_phys_addr_valid(paddr) ) + if (!ia64_phys_addr_valid(paddr)) return ISOLATE_NG; /* convert physical address to physical page number */ p = pfn_to_page(paddr>>PAGE_SHIFT); /* check whether a page number have been already registered or not */ - for( i = 0; i < num_page_isolate; i++ ) - if( page_isolate[i] == p ) + for (i = 0; i < num_page_isolate; i++) + if (page_isolate[i] == p) return ISOLATE_OK; /* already listed */ /* limitation check */ - if( num_page_isolate == MAX_PAGE_ISOLATE ) + if (num_page_isolate == MAX_PAGE_ISOLATE) return ISOLATE_NG; /* kick pages having attribute 'SLAB' or 'Reserved' */ - if( PageSlab(p) || PageReserved(p) ) + if (PageSlab(p) || PageReserved(p)) return ISOLATE_NG; /* add attribute 'Reserved' and register the page */ @@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr) * @peidx: pointer to index of processor error section */ -static void +static void mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) { - /* + /* * calculate the start address of * "struct cpuid_info" and "sal_processor_static_info_t". */ @@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) } /** - * mca_make_slidx - Make index of SAL error record + * mca_make_slidx - Make index of SAL error record * @buffer: pointer to SAL error record * @slidx: pointer to index of SAL error record * @@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) * 1 if record has platform error / 0 if not */ #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \ - { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ - hl->hdr = ptr; \ - list_add(&hl->list, &(sect)); \ - slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } + {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ + hl->hdr = ptr; \ + list_add(&hl->list, &(sect)); \ + slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } -static int +static int mca_make_slidx(void *buffer, slidx_table_t *slidx) { int platform_err = 0; @@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos); if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) { LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp); - } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) { + } else if (!efi_guidcmp(sp->guid, + SAL_PLAT_BUS_ERR_SECT_GUID)) { platform_err = 1; LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp); } else { @@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) * Return value: * 0 on Success / -ENOMEM on Failure */ -static int +static int init_record_index_pools(void) { int i; int rec_max_size; /* Maximum size of SAL error records */ int sect_min_size; /* Minimum size of SAL error sections */ /* minimum size table of each section */ - static int sal_log_sect_min_sizes[] = { - sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t), + static int sal_log_sect_min_sizes[] = { + sizeof(sal_log_processor_info_t) + + sizeof(sal_processor_static_info_t), sizeof(sal_log_mem_dev_err_info_t), sizeof(sal_log_sel_dev_err_info_t), sizeof(sal_log_pci_bus_err_info_t), @@ -294,7 +303,8 @@ init_record_index_pools(void) /* - 3 - */ slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; - slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); + slidx_pool.buffer = (slidx_list_t *) + kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); return slidx_pool.buffer ? 0 : -ENOMEM; } @@ -308,6 +318,7 @@ init_record_index_pools(void) * is_mca_global - Check whether this MCA is global or not * @peidx: pointer of index of processor error section * @pbci: pointer to pal_bus_check_info_t + * @sos: pointer to hand off struct between SAL and OS * * Return value: * MCA_IS_LOCAL / MCA_IS_GLOBAL @@ -317,11 +328,12 @@ static mca_type_t is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); - /* + /* * PAL can request a rendezvous, if the MCA has a global scope. - * If "rz_always" flag is set, SAL requests MCA rendezvous + * If "rz_always" flag is set, SAL requests MCA rendezvous * in spite of global MCA. * Therefore it is local MCA when rendezvous has not been requested. * Failed to rendezvous, the system must be down. @@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_read_error(slidx_table_t *slidx, + peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { sal_log_mod_error_info_t *smei; @@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, + pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { int status = 0; - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); if (psp->bc && pbci->eb && pbci->bsi == 0) { switch(pbci->type) { case 1: /* partial read */ case 3: /* full line(cpu) read */ case 9: /* I/O space read */ - status = recover_from_read_error(slidx, peidx, pbci, sos); + status = recover_from_read_error(slidx, peidx, pbci, + sos); break; case 0: /* unknown */ case 2: /* partial write */ @@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ case 8: /* write coalescing transactions */ case 10: /* I/O space write */ case 11: /* inter-processor interrupt message(IPI) */ - case 12: /* interrupt acknowledge or external task priority cycle */ + case 12: /* interrupt acknowledge or + external task priority cycle */ default: break; } @@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ * @slidx: pointer of index of SAL error record * @peidx: pointer of index of processor error section * @pbci: pointer of pal_bus_check_info + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure @@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ */ static int -recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, +recover_from_processor_error(int platform, slidx_table_t *slidx, + peidx_table_t *peidx, pal_bus_check_info_t *pbci, struct ia64_sal_os_state *sos) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); + pal_processor_state_info_t *psp = + (pal_processor_state_info_t*)peidx_psp(peidx); - /* + /* * We cannot recover errors with other than bus_check. */ - if (psp->cc || psp->rc || psp->uc) + if (psp->cc || psp->rc || psp->uc) return 0; /* @@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * * (e.g. a load from poisoned memory) * This means "there are some platform errors". */ - if (platform) + if (platform) return recover_from_platform_error(slidx, peidx, pbci, sos); - /* - * On account of strange SAL error record, we cannot recover. + /* + * On account of strange SAL error record, we cannot recover. */ return 0; } @@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * /** * mca_try_to_recover - Try to recover from MCA * @rec: pointer to a SAL error record + * @sos: pointer to hand off struct between SAL and OS * * Return value: * 1 on Success / 0 on Failure */ static int -mca_try_to_recover(void *rec, - struct ia64_sal_os_state *sos) +mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos) { int platform_err; int n_proc_err; @@ -588,7 +610,8 @@ mca_try_to_recover(void *rec, } /* Make index of processor error section */ - mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx); + mca_make_peidx((sal_log_processor_info_t*) + slidx_first_entry(&slidx.proc_err)->hdr, &peidx); /* Extract Processor BUS_CHECK[0] */ *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0); @@ -598,7 +621,8 @@ mca_try_to_recover(void *rec, return 0; /* Try to recover a processor error */ - return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos); + return recover_from_processor_error(platform_err, &slidx, &peidx, + &pbci, sos); } /* @@ -611,7 +635,7 @@ int __init mca_external_handler_init(void) return -ENOMEM; /* register external mca handlers */ - if (ia64_reg_MCA_extension(mca_try_to_recover)){ + if (ia64_reg_MCA_extension(mca_try_to_recover)) { printk(KERN_ERR "ia64_reg_MCA_extension failed.\n"); kfree(slidx_pool.buffer); return -EFAULT; diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h index 0227b76..e2f6fa1 100644 --- a/arch/ia64/kernel/mca_drv.h +++ b/arch/ia64/kernel/mca_drv.h @@ -6,7 +6,7 @@ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com) */ /* - * Processor error section: + * Processor error section: * * +-sal_log_processor_info_t *info-------------+ * | sal_log_section_hdr_t header; | diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S index 2d7e021..3f298ee 100644 --- a/arch/ia64/kernel/mca_drv_asm.S +++ b/arch/ia64/kernel/mca_drv_asm.S @@ -13,45 +13,45 @@ #include GLOBAL_ENTRY(mca_handler_bhhook) - invala // clear RSE ? - ;; // - cover // - ;; // - clrrrb // + invala // clear RSE ? + ;; + cover + ;; + clrrrb ;; - alloc r16=ar.pfs,0,2,1,0 // make a new frame + alloc r16=ar.pfs,0,2,1,0 // make a new frame ;; - mov ar.rsc=0 + mov ar.rsc=0 ;; - mov r13=IA64_KR(CURRENT) // current task pointer + mov r13=IA64_KR(CURRENT) // current task pointer ;; - mov r2=r13 + mov r2=r13 ;; - addl r22=IA64_RBS_OFFSET,r2 + addl r22=IA64_RBS_OFFSET,r2 ;; - mov ar.bspstore=r22 + mov ar.bspstore=r22 ;; - addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 + addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 ;; - adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 ;; - st1 [r2]=r0 // clear current->thread.on_ustack flag - mov loc0=r16 - movl loc1=mca_handler_bh // recovery C function + st1 [r2]=r0 // clear current->thread.on_ustack flag + mov loc0=r16 + movl loc1=mca_handler_bh // recovery C function ;; - mov out0=r8 // poisoned address - mov b6=loc1 + mov out0=r8 // poisoned address + mov b6=loc1 ;; - mov loc1=rp + mov loc1=rp ;; - ssm psr.i + ssm psr.i ;; - br.call.sptk.many rp=b6 // does not return ... + br.call.sptk.many rp=b6 // does not return ... ;; - mov ar.pfs=loc0 - mov rp=loc1 + mov ar.pfs=loc0 + mov rp=loc1 ;; - mov r8=r0 + mov r8=r0 br.ret.sptk.many rp ;; END(mca_handler_bhhook) -- cgit v0.10.2 From a063cf5b7dde94d98f3f7c9f1c951e02c6564022 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Fri, 16 Sep 2005 19:32:53 +0200 Subject: [PATCH] Add PCI IDs for Sitecom DC-105 Sitecom DC-105 PCI work with hfc_pci HiSax driver Signed-off-by: Karsten Keil Signed-off-by: Linus Torvalds diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 8337b0f..4866fc3 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] = {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, + {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"}, {0, 0, NULL, NULL}, }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 72fe338..b6ef7eb 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2252,6 +2252,9 @@ #define PCI_VENDOR_ID_INFINICON 0x1820 +#define PCI_VENDOR_ID_SITECOM 0x182d +#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 + #define PCI_VENDOR_ID_TOPSPIN 0x1867 #define PCI_VENDOR_ID_TDI 0x192E -- cgit v0.10.2 From 06168d8a10ceccced51380d683245b33474d428a Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Fri, 16 Sep 2005 19:34:17 +0200 Subject: [PATCH] cleanup whitespace in pci_ids.h Signed-off-by: Karsten Keil Signed-off-by: Linus Torvalds diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b6ef7eb..486d1c1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2254,7 +2254,7 @@ #define PCI_VENDOR_ID_SITECOM 0x182d #define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 - + #define PCI_VENDOR_ID_TOPSPIN 0x1867 #define PCI_VENDOR_ID_TDI 0x192E -- cgit v0.10.2 From 37f7f421cce13435fdc0d870caf51141e5ebf079 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 16 Sep 2005 16:51:01 -0700 Subject: [NET]: Do not leak MSG_CMSG_COMPAT into userspace. Noticed by Sridhar Samudrala. Signed-off-by: David S. Miller diff --git a/net/socket.c b/net/socket.c index c699e93..f926447 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1862,7 +1862,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag if (err < 0) goto out_freeiov; } - err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg)); + err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT), + COMPAT_FLAGS(msg)); if (err) goto out_freeiov; if (MSG_CMSG_COMPAT & flags) -- cgit v0.10.2 From 0c10c5d96865ce611d6a780888eff0ef4fab358b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 16 Sep 2005 16:58:33 -0700 Subject: [DCCP]: More precisely set reset_code when sending RESET packets Moving the setting of DCCP_SKB_CB(skb)->dccpd_reset_code to the places where events happen that trigger sending a RESET packet. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/dccp/input.c b/net/dccp/input.c index c74034c..062e9f8 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -384,9 +384,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, } out_invalid_packet: - return 1; /* dccp_v4_do_rcv will send a reset, but... - FIXME: the reset code should be - DCCP_RESET_CODE_PACKET_ERROR */ + /* dccp_v4_do_rcv will send a reset */ + DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; + return 1; } static int dccp_rcv_respond_partopen_state_process(struct sock *sk, @@ -433,6 +433,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct dccp_hdr *dh, unsigned len) { struct dccp_sock *dp = dccp_sk(sk); + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); const int old_state = sk->sk_state; int queued = 0; @@ -473,7 +474,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dh->dccph_type == DCCP_PKT_RESET) goto discard; - /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/ + /* Caller (dccp_v4_do_rcv) will send Reset */ + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; return 1; } @@ -487,8 +489,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dccp_parse_options(sk, skb)) goto discard; - if (DCCP_SKB_CB(skb)->dccpd_ack_seq != - DCCP_PKT_WITHOUT_ACK_SEQ) + if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); @@ -500,7 +501,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, */ if (dp->dccps_options.dccpo_send_ack_vector) { if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_seq, + dcb->dccpd_seq, DCCP_ACKPKTS_STATE_RECEIVED)) goto discard; /* @@ -551,8 +552,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, dh->dccph_type == DCCP_PKT_REQUEST) || (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_PKT_SYNC); + dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); goto discard; } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { dccp_rcv_closereq(sk, skb); @@ -563,13 +563,13 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { - dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_PKT_SYNCACK); + dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK); goto discard; } switch (sk->sk_state) { case DCCP_CLOSED: + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; return 1; case DCCP_REQUESTING: diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 2afaa46..e09907d 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -669,12 +669,16 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_request_sock *dreq; const __u32 saddr = skb->nh.iph->saddr; const __u32 daddr = skb->nh.iph->daddr; + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); + __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; struct dst_entry *dst = NULL; /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ if (((struct rtable *)skb->dst)->rt_flags & - (RTCF_BROADCAST | RTCF_MULTICAST)) + (RTCF_BROADCAST | RTCF_MULTICAST)) { + reset_code = DCCP_RESET_CODE_NO_CONNECTION; goto drop; + } /* * TW buckets are converted to open requests without @@ -718,7 +722,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * dccp_create_openreq_child. */ dreq = dccp_rsk(req); - dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; + dreq->dreq_isr = dcb->dccpd_seq; dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; @@ -735,6 +739,7 @@ drop_and_free: __reqsk_free(req); drop: DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); + dcb->dccpd_reset_code = reset_code; return -1; } @@ -1005,7 +1010,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; dccp_v4_ctl_send_reset(skb); discard: kfree_skb(skb); -- cgit v0.10.2 From 67e6b629212fa9ffb7420e8a88a41806af637e28 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 16 Sep 2005 16:58:40 -0700 Subject: [DCCP]: Introduce DCCP_SOCKOPT_SERVICE As discussed in the dccp@vger mailing list: Now applications have to use setsockopt(DCCP_SOCKOPT_SERVICE, service[s]), prior to calling listen() and connect(). An array of unsigned ints can be passed meaning that the listening sock accepts connection requests for several services. With this we can ditch struct sockaddr_dccp and use only sockaddr_in (and sockaddr_in6 in the future). Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 8bf4bac..0e72708 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -4,16 +4,6 @@ #include #include -/* Structure describing an Internet (DCCP) socket address. */ -struct sockaddr_dccp { - __u16 sdccp_family; /* Address family */ - __u16 sdccp_port; /* Port number */ - __u32 sdccp_addr; /* Internet address */ - __u32 sdccp_service; /* Service */ - /* Pad to size of `struct sockaddr': 16 bytes . */ - __u32 sdccp_pad; -}; - /** * struct dccp_hdr - generic part of DCCP packet header * @@ -188,6 +178,9 @@ enum { /* DCCP socket options */ #define DCCP_SOCKOPT_PACKET_SIZE 1 +#define DCCP_SOCKOPT_SERVICE 2 + +#define DCCP_SERVICE_LIST_MAX_LEN 32 #ifdef __KERNEL__ @@ -382,6 +375,25 @@ enum dccp_role { DCCP_ROLE_SERVER, }; +struct dccp_service_list { + __u32 dccpsl_nr; + __u32 dccpsl_list[0]; +}; + +#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) + +static inline int dccp_list_has_service(const struct dccp_service_list *sl, + const u32 service) +{ + if (likely(sl != NULL)) { + u32 i = sl->dccpsl_nr; + while (i--) + if (sl->dccpsl_list[i] == service) + return 1; + } + return 0; +} + /** * struct dccp_sock - DCCP socket state * @@ -417,7 +429,8 @@ struct dccp_sock { __u64 dccps_gss; __u64 dccps_gsr; __u64 dccps_gar; - unsigned long dccps_service; + __u32 dccps_service; + struct dccp_service_list *dccps_service_list; struct timeval dccps_timestamp_time; __u32 dccps_timestamp_echo; __u32 dccps_packet_size; @@ -443,6 +456,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) return (struct dccp_sock *)sk; } +static inline int dccp_service_not_initialized(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; +} + static inline const char *dccp_role(const struct sock *sk) { switch (dccp_sk(sk)->dccps_role) { diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 95c4630..be7a660 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -258,13 +258,12 @@ extern int dccp_v4_send_reset(struct sock *sk, extern void dccp_send_close(struct sock *sk, const int active); struct dccp_skb_cb { - __u8 dccpd_type; - __u8 dccpd_reset_code; - __u8 dccpd_service; - __u8 dccpd_ccval; + __u8 dccpd_type:4; + __u8 dccpd_ccval:4; + __u8 dccpd_reset_code; + __u16 dccpd_opt_len; __u64 dccpd_seq; __u64 dccpd_ack_seq; - int dccpd_opt_len; }; #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0])) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index e09907d..94a440b 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -246,6 +246,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, dp->dccps_role = DCCP_ROLE_CLIENT; + if (dccp_service_not_initialized(sk)) + return -EPROTO; + if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; @@ -661,6 +664,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk, dccp_hdr(skb)->dccph_sport); } +static inline int dccp_bad_service_code(const struct sock *sk, + const __u32 service) +{ + const struct dccp_sock *dp = dccp_sk(sk); + + if (dp->dccps_service == service) + return 0; + return !dccp_list_has_service(dp->dccps_service_list, service); +} + int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) { struct inet_request_sock *ireq; @@ -669,6 +682,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) struct dccp_request_sock *dreq; const __u32 saddr = skb->nh.iph->saddr; const __u32 daddr = skb->nh.iph->daddr; + const __u32 service = dccp_hdr_request(skb)->dccph_req_service; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; struct dst_entry *dst = NULL; @@ -680,6 +694,10 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop; } + if (dccp_bad_service_code(sk, service)) { + reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; + goto drop; + } /* * TW buckets are converted to open requests without * limitations, they conserve resources and peer is @@ -722,9 +740,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * dccp_create_openreq_child. */ dreq = dccp_rsk(req); - dreq->dreq_isr = dcb->dccpd_seq; - dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); - dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; + dreq->dreq_isr = dcb->dccpd_seq; + dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); + dreq->dreq_service = service; if (dccp_v4_send_response(sk, req, dst)) goto drop_and_free; @@ -1284,6 +1302,7 @@ static int dccp_v4_init_sock(struct sock *sk) sk->sk_write_space = dccp_write_space; dp->dccps_mss_cache = 536; dp->dccps_role = DCCP_ROLE_UNDEFINED; + dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; return 0; } @@ -1305,6 +1324,11 @@ static int dccp_v4_destroy_sock(struct sock *sk) if (inet_csk(sk)->icsk_bind_hash != NULL) inet_put_port(&dccp_hashinfo, sk); + if (dp->dccps_service_list != NULL) { + kfree(dp->dccps_service_list); + dp->dccps_service_list = NULL; + } + ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 18461bc..933e10d 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -93,9 +93,11 @@ struct sock *dccp_create_openreq_child(struct sock *sk, struct inet_connection_sock *newicsk = inet_csk(sk); struct dccp_sock *newdp = dccp_sk(newsk); + newdp->dccps_role = DCCP_ROLE_SERVER; newdp->dccps_hc_rx_ackpkts = NULL; - newdp->dccps_role = DCCP_ROLE_SERVER; - newicsk->icsk_rto = DCCP_TIMEOUT_INIT; + newdp->dccps_service_list = NULL; + newdp->dccps_service = dreq->dreq_service; + newicsk->icsk_rto = DCCP_TIMEOUT_INIT; do_gettimeofday(&newdp->dccps_epoch); if (newdp->dccps_options.dccpo_send_ack_vector) { diff --git a/net/dccp/output.c b/net/dccp/output.c index ea6d0e9..156b1d2 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -85,7 +85,7 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) switch (dcb->dccpd_type) { case DCCP_PKT_REQUEST: dccp_hdr_request(skb)->dccph_req_service = - dcb->dccpd_service; + dp->dccps_service; break; case DCCP_PKT_RESET: dccp_hdr_reset(skb)->dccph_reset_code = @@ -270,6 +270,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, struct request_sock *req) { struct dccp_hdr *dh; + struct dccp_request_sock *dreq; const int dccp_header_size = sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_response); @@ -285,8 +286,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, skb->dst = dst_clone(dst); skb->csum = 0; + dreq = dccp_rsk(req); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; - DCCP_SKB_CB(skb)->dccpd_seq = dccp_rsk(req)->dreq_iss; + DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; dccp_insert_options(sk, skb); skb->h.raw = skb_push(skb, dccp_header_size); @@ -300,8 +302,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, DCCP_SKB_CB(skb)->dccpd_opt_len) / 4; dh->dccph_type = DCCP_PKT_RESPONSE; dh->dccph_x = 1; - dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss); - dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr); + dccp_hdr_set_seq(dh, dreq->dreq_iss); + dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); + dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, inet_rsk(req)->rmt_addr); @@ -397,9 +400,6 @@ int dccp_connect(struct sock *sk) skb_reserve(skb, MAX_DCCP_HEADER); DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; - /* FIXME: set service to something meaningful, coming - * from userspace*/ - DCCP_SKB_CB(skb)->dccpd_service = 0; skb->csum = 0; skb_set_owner_w(skb, sk); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 18a0e69..9bda286 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -94,7 +94,15 @@ EXPORT_SYMBOL_GPL(dccp_state_name); static inline int dccp_listen_start(struct sock *sk) { - dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN; + struct dccp_sock *dp = dccp_sk(sk); + + dp->dccps_role = DCCP_ROLE_LISTEN; + /* + * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE) + * before calling listen() + */ + if (dccp_service_not_initialized(sk)) + return -EPROTO; return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); } @@ -202,6 +210,42 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) return -ENOIOCTLCMD; } +static int dccp_setsockopt_service(struct sock *sk, const u32 service, + char __user *optval, int optlen) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_service_list *sl = NULL; + + if (service == DCCP_SERVICE_INVALID_VALUE || + optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32)) + return -EINVAL; + + if (optlen > sizeof(service)) { + sl = kmalloc(optlen, GFP_KERNEL); + if (sl == NULL) + return -ENOMEM; + + sl->dccpsl_nr = optlen / sizeof(u32) - 1; + if (copy_from_user(sl->dccpsl_list, + optval + sizeof(service), + optlen - sizeof(service)) || + dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) { + kfree(sl); + return -EFAULT; + } + } + + lock_sock(sk); + dp->dccps_service = service; + + if (dp->dccps_service_list != NULL) + kfree(dp->dccps_service_list); + + dp->dccps_service_list = sl; + release_sock(sk); + return 0; +} + int dccp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen) { @@ -218,8 +262,10 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, if (get_user(val, (int __user *)optval)) return -EFAULT; - lock_sock(sk); + if (optname == DCCP_SOCKOPT_SERVICE) + return dccp_setsockopt_service(sk, val, optval, optlen); + lock_sock(sk); dp = dccp_sk(sk); err = 0; @@ -236,6 +282,37 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, return err; } +static int dccp_getsockopt_service(struct sock *sk, int len, + u32 __user *optval, + int __user *optlen) +{ + const struct dccp_sock *dp = dccp_sk(sk); + const struct dccp_service_list *sl; + int err = -ENOENT, slen = 0, total_len = sizeof(u32); + + lock_sock(sk); + if (dccp_service_not_initialized(sk)) + goto out; + + if ((sl = dp->dccps_service_list) != NULL) { + slen = sl->dccpsl_nr * sizeof(u32); + total_len += slen; + } + + err = -EINVAL; + if (total_len > len) + goto out; + + err = 0; + if (put_user(total_len, optlen) || + put_user(dp->dccps_service, optval) || + (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen))) + err = -EFAULT; +out: + release_sock(sk); + return err; +} + int dccp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) { @@ -248,6 +325,10 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; + if (optname == DCCP_SOCKOPT_SERVICE) + return dccp_getsockopt_service(sk, len, + (u32 __user *)optval, optlen); + len = min_t(unsigned int, len, sizeof(int)); if (len < 0) return -EINVAL; -- cgit v0.10.2 From 1cbf07478bbf3e350a2025bc5ea23fedaa95855a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 16 Sep 2005 16:59:20 -0700 Subject: [TG3]: Add AMD K8 to list of write-reorder chipsets. Thanks to Andy Stewart for the report and testing debug patches from Michael Chan. Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7599f52..52eae9f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.39" -#define DRV_MODULE_RELDATE "September 5, 2005" +#define DRV_MODULE_VERSION "3.40" +#define DRV_MODULE_RELDATE "September 15, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -9271,6 +9271,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) static struct pci_device_id write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_K8_NB) }, { }, }; u32 misc_ctrl_reg; @@ -9285,7 +9287,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_SUN_570X; #endif - /* If we have an AMD 762 chipset, write + /* If we have an AMD 762 or K8 chipset, write * reordering to the mailbox registers done by the host * controller can cause major troubles. We read back from * every mailbox register write to force the writes to be diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 72fe338..3dc1618 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -491,6 +491,7 @@ #define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 #define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_K8_NB 0x1100 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 #define PCI_DEVICE_ID_AMD_SCSI 0x2020 -- cgit v0.10.2 From 4451362445b2d83886003f1d739b94e4f000eeeb Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Fri, 16 Sep 2005 16:59:46 -0700 Subject: [NETFILTER] CLUSTERIP: introduce reference counting for entries The CLUSTERIP target creates a procfs entry for all different cluster IPs. Although more than one rules can refer to a single cluster IP (and thus a single config structure), removal of the procfs entry is done unconditionally in destroy(). In more complicated situations involving deferred dereferencing of the config structure by procfs and creating a new rule with the same cluster IP it's also possible that no entry will be created for the new rule. This patch fixes the problem by counting the number of entries referencing a given config structure and moving the config list manipulation and procfs entry deletion parts to the clusterip_config_entry_put() function. Signed-off-by: KOVACS Krisztian Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 7d38913..adbf4d7 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -49,6 +49,8 @@ MODULE_DESCRIPTION("iptables target for CLUSTERIP"); struct clusterip_config { struct list_head list; /* list of all configs */ atomic_t refcount; /* reference count */ + atomic_t entries; /* number of entries/rules + * referencing us */ u_int32_t clusterip; /* the IP address */ u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ @@ -76,23 +78,48 @@ static struct proc_dir_entry *clusterip_procdir; #endif static inline void -clusterip_config_get(struct clusterip_config *c) { +clusterip_config_get(struct clusterip_config *c) +{ atomic_inc(&c->refcount); } static inline void -clusterip_config_put(struct clusterip_config *c) { - if (atomic_dec_and_test(&c->refcount)) { +clusterip_config_put(struct clusterip_config *c) +{ + if (atomic_dec_and_test(&c->refcount)) + kfree(c); +} + +/* increase the count of entries(rules) using/referencing this config */ +static inline void +clusterip_config_entry_get(struct clusterip_config *c) +{ + atomic_inc(&c->entries); +} + +/* decrease the count of entries using/referencing this config. If last + * entry(rule) is removed, remove the config from lists, but don't free it + * yet, since proc-files could still be holding references */ +static inline void +clusterip_config_entry_put(struct clusterip_config *c) +{ + if (atomic_dec_and_test(&c->entries)) { write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); + dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); dev_put(c->dev); - kfree(c); + + /* In case anyone still accesses the file, the open/close + * functions are also incrementing the refcount on their own, + * so it's safe to remove the entry even if it's in use. */ +#ifdef CONFIG_PROC_FS + remove_proc_entry(c->pde->name, c->pde->parent); +#endif } } - static struct clusterip_config * __clusterip_config_find(u_int32_t clusterip) { @@ -111,7 +138,7 @@ __clusterip_config_find(u_int32_t clusterip) } static inline struct clusterip_config * -clusterip_config_find_get(u_int32_t clusterip) +clusterip_config_find_get(u_int32_t clusterip, int entry) { struct clusterip_config *c; @@ -122,6 +149,8 @@ clusterip_config_find_get(u_int32_t clusterip) return NULL; } atomic_inc(&c->refcount); + if (entry) + atomic_inc(&c->entries); read_unlock_bh(&clusterip_lock); return c; @@ -148,6 +177,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, c->hash_mode = i->hash_mode; c->hash_initval = i->hash_initval; atomic_set(&c->refcount, 1); + atomic_set(&c->entries, 1); #ifdef CONFIG_PROC_FS /* create proc dir entry */ @@ -415,8 +445,26 @@ checkentry(const char *tablename, /* FIXME: further sanity checks */ - config = clusterip_config_find_get(e->ip.dst.s_addr); - if (!config) { + config = clusterip_config_find_get(e->ip.dst.s_addr, 1); + if (config) { + if (cipinfo->config != NULL) { + /* Case A: This is an entry that gets reloaded, since + * it still has a cipinfo->config pointer. Simply + * increase the entry refcount and return */ + if (cipinfo->config != config) { + printk(KERN_ERR "CLUSTERIP: Reloaded entry " + "has invalid config pointer!\n"); + return 0; + } + clusterip_config_entry_get(cipinfo->config); + } else { + /* Case B: This is a new rule referring to an existing + * clusterip config. */ + cipinfo->config = config; + clusterip_config_entry_get(cipinfo->config); + } + } else { + /* Case C: This is a completely new clusterip config */ if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); return 0; @@ -443,10 +491,9 @@ checkentry(const char *tablename, } dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); } + cipinfo->config = config; } - cipinfo->config = config; - return 1; } @@ -455,13 +502,10 @@ static void destroy(void *matchinfo, unsigned int matchinfosize) { struct ipt_clusterip_tgt_info *cipinfo = matchinfo; - /* we first remove the proc entry and then drop the reference - * count. In case anyone still accesses the file, the open/close - * functions are also incrementing the refcount on their own */ -#ifdef CONFIG_PROC_FS - remove_proc_entry(cipinfo->config->pde->name, - cipinfo->config->pde->parent); -#endif + /* if no more entries are referencing the config, remove it + * from the list and destroy the proc entry */ + clusterip_config_entry_put(cipinfo->config); + clusterip_config_put(cipinfo->config); } @@ -533,7 +577,7 @@ arp_mangle(unsigned int hook, /* if there is no clusterip configuration for the arp reply's * source ip, we don't want to mangle it */ - c = clusterip_config_find_get(payload->src_ip); + c = clusterip_config_find_get(payload->src_ip, 0); if (!c) return NF_ACCEPT; -- cgit v0.10.2 From 136e92bbec0a6d4c2dd1e5b5ac869ab5470547a4 Mon Sep 17 00:00:00 2001 From: KOVACS Krisztian Date: Fri, 16 Sep 2005 17:00:04 -0700 Subject: [NETFILTER] CLUSTERIP: use a bitmap to store node responsibility data Instead of maintaining an array containing a list of nodes this instance is responsible for let's use a simple bitmap. This provides the following features: * clusterip_responsible() and the add_node()/delete_node() operations become very simple and don't need locking * the config structure is much smaller In spite of the completely different internal data representation the user-space interface remains almost unchanged; the only difference is that the proc file does not list nodes in the order they were added. (The target info structure remains the same.) Signed-off-by: KOVACS Krisztian Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index adbf4d7..9bcb398 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ #include #include -#define CLUSTERIP_VERSION "0.7" +#define CLUSTERIP_VERSION "0.8" #define DEBUG_CLUSTERIP @@ -56,8 +57,7 @@ struct clusterip_config { u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ struct net_device *dev; /* device */ u_int16_t num_total_nodes; /* total number of nodes */ - u_int16_t num_local_nodes; /* number of local nodes */ - u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; /* node number array */ + unsigned long local_nodes; /* node number array */ #ifdef CONFIG_PROC_FS struct proc_dir_entry *pde; /* proc dir entry */ @@ -68,8 +68,7 @@ struct clusterip_config { static LIST_HEAD(clusterip_configs); -/* clusterip_lock protects the clusterip_configs list _AND_ the configurable - * data within all structurses (num_local_nodes, local_nodes[]) */ +/* clusterip_lock protects the clusterip_configs list */ static DEFINE_RWLOCK(clusterip_lock); #ifdef CONFIG_PROC_FS @@ -156,6 +155,17 @@ clusterip_config_find_get(u_int32_t clusterip, int entry) return c; } +static void +clusterip_config_init_nodelist(struct clusterip_config *c, + const struct ipt_clusterip_tgt_info *i) +{ + int n; + + for (n = 0; n < i->num_local_nodes; n++) { + set_bit(i->local_nodes[n] - 1, &c->local_nodes); + } +} + static struct clusterip_config * clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, struct net_device *dev) @@ -172,8 +182,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, c->clusterip = ip; memcpy(&c->clustermac, &i->clustermac, ETH_ALEN); c->num_total_nodes = i->num_total_nodes; - c->num_local_nodes = i->num_local_nodes; - memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes)); + clusterip_config_init_nodelist(c, i); c->hash_mode = i->hash_mode; c->hash_initval = i->hash_initval; atomic_set(&c->refcount, 1); @@ -201,53 +210,28 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, static int clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) { - int i; - - write_lock_bh(&clusterip_lock); - if (c->num_local_nodes >= CLUSTERIP_MAX_NODES - || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + if (nodenum == 0 || + nodenum > c->num_total_nodes) return 1; - } - - /* check if we alrady have this number in our array */ - for (i = 0; i < c->num_local_nodes; i++) { - if (c->local_nodes[i] == nodenum) { - write_unlock_bh(&clusterip_lock); - return 1; - } - } - c->local_nodes[c->num_local_nodes++] = nodenum; + /* check if we already have this number in our bitfield */ + if (test_and_set_bit(nodenum - 1, &c->local_nodes)) + return 1; - write_unlock_bh(&clusterip_lock); return 0; } static int clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) { - int i; - - write_lock_bh(&clusterip_lock); - - if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + if (nodenum == 0 || + nodenum > c->num_total_nodes) return 1; - } - for (i = 0; i < c->num_local_nodes; i++) { - if (c->local_nodes[i] == nodenum) { - int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1)); - memmove(&c->local_nodes[i], &c->local_nodes[i+1], size); - c->num_local_nodes--; - write_unlock_bh(&clusterip_lock); - return 0; - } - } + if (test_and_clear_bit(nodenum - 1, &c->local_nodes)) + return 0; - write_unlock_bh(&clusterip_lock); return 1; } @@ -315,25 +299,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) static inline int clusterip_responsible(struct clusterip_config *config, u_int32_t hash) { - int i; - - read_lock_bh(&clusterip_lock); - - if (config->num_local_nodes == 0) { - read_unlock_bh(&clusterip_lock); - return 0; - } - - for (i = 0; i < config->num_local_nodes; i++) { - if (config->local_nodes[i] == hash) { - read_unlock_bh(&clusterip_lock); - return 1; - } - } - - read_unlock_bh(&clusterip_lock); - - return 0; + return test_bit(hash - 1, &config->local_nodes); } /*********************************************************************** @@ -618,56 +584,69 @@ static struct nf_hook_ops cip_arp_ops = { #ifdef CONFIG_PROC_FS +struct clusterip_seq_position { + unsigned int pos; /* position */ + unsigned int weight; /* number of bits set == size */ + unsigned int bit; /* current bit */ + unsigned long val; /* current value */ +}; + static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) { struct proc_dir_entry *pde = s->private; struct clusterip_config *c = pde->data; - unsigned int *nodeidx; - - read_lock_bh(&clusterip_lock); - if (*pos >= c->num_local_nodes) + unsigned int weight; + u_int32_t local_nodes; + struct clusterip_seq_position *idx; + + /* FIXME: possible race */ + local_nodes = c->local_nodes; + weight = hweight32(local_nodes); + if (*pos >= weight) return NULL; - nodeidx = kmalloc(sizeof(unsigned int), GFP_KERNEL); - if (!nodeidx) + idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL); + if (!idx) return ERR_PTR(-ENOMEM); - *nodeidx = *pos; - return nodeidx; + idx->pos = *pos; + idx->weight = weight; + idx->bit = ffs(local_nodes); + idx->val = local_nodes; + clear_bit(idx->bit - 1, &idx->val); + + return idx; } static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) { - struct proc_dir_entry *pde = s->private; - struct clusterip_config *c = pde->data; - unsigned int *nodeidx = (unsigned int *)v; + struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; - *pos = ++(*nodeidx); - if (*pos >= c->num_local_nodes) { + *pos = ++idx->pos; + if (*pos >= idx->weight) { kfree(v); return NULL; } - return nodeidx; + idx->bit = ffs(idx->val); + clear_bit(idx->bit - 1, &idx->val); + return idx; } static void clusterip_seq_stop(struct seq_file *s, void *v) { kfree(v); - - read_unlock_bh(&clusterip_lock); } static int clusterip_seq_show(struct seq_file *s, void *v) { - struct proc_dir_entry *pde = s->private; - struct clusterip_config *c = pde->data; - unsigned int *nodeidx = (unsigned int *)v; + struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; - if (*nodeidx != 0) + if (idx->pos != 0) seq_putc(s, ','); - seq_printf(s, "%u", c->local_nodes[*nodeidx]); - if (*nodeidx == c->num_local_nodes-1) + seq_printf(s, "%u", idx->bit); + + if (idx->pos == idx->weight - 1) seq_putc(s, '\n'); return 0; -- cgit v0.10.2 From a8f39143ac67ffa2e26ce48aaac6bf5dc7dae95f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 16 Sep 2005 17:00:38 -0700 Subject: [NETFILTER]: Fix oops in conntrack event cache ip_ct_refresh_acct() can be called without a valid "skb" pointer. This used to work, since ct_add_counters() deals with that fact. However, the recently-added event cache doesn't handle this at all. This patch is a quick fix that is supposed to be replaced soon by a cleaner solution during the pending redesign of the event cache. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 19cba16..f8cd8e4 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1143,7 +1143,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; add_timer(&ct->timeout); - ip_conntrack_event_cache(IPCT_REFRESH, skb); + /* FIXME: We loose some REFRESH events if this function + * is called without an skb. I'll fix this later -HW */ + if (skb) + ip_conntrack_event_cache(IPCT_REFRESH, skb); } ct_add_counters(ct, ctinfo, skb); write_unlock_bh(&ip_conntrack_lock); -- cgit v0.10.2 From 22abe310bc4b0c684fd3716af6b6116ff1011707 Mon Sep 17 00:00:00 2001 From: Peter Hagervall Date: Fri, 16 Sep 2005 17:01:03 -0700 Subject: [TG3]: Sparse fixes for tg3 Change 0 to NULL where appropriate. Signed-off-by: Peter Hagervall Acked-by: Jeff Garzik Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 52eae9f..06b02c5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9534,7 +9534,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->write32_rx_mbox = tg3_write_indirect_mbox; iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); pci_cmd &= ~PCI_COMMAND_MEMORY; @@ -10682,7 +10682,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err_out_iounmap: if (tp->regs) { iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; } err_out_free_dev: @@ -10707,7 +10707,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) unregister_netdev(dev); if (tp->regs) { iounmap(tp->regs); - tp->regs = 0; + tp->regs = NULL; } free_netdev(dev); pci_release_regions(pdev); -- cgit v0.10.2 From 777ed97f3e549832845d70dcae96cb36c41a543a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 17 Sep 2005 00:41:02 -0700 Subject: [NETFILTER] Fix Kconfig dependencies for nfnetlink/ctnetlink Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 30aa8e2..85190de 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -8,6 +8,7 @@ menu "IP: Netfilter Configuration" # connection tracking, helpers and protocols config IP_NF_CONNTRACK tristate "Connection tracking (required for masq/NAT)" + select NETFILTER_NETLINK if IP_NF_CONNTRACK_NETLINK!=n ---help--- Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related @@ -51,6 +52,15 @@ config IP_NF_CONNTRACK_EVENTS IF unsure, say `N'. +config IP_NF_CONNTRACK_NETLINK + tristate 'Connection tracking netlink interface' + depends on IP_NF_CONNTRACK && NETFILTER_NETLINK + default IP_NF_CONNTRACK if NETFILTER_NETLINK=y + default m if NETFILTER_NETLINK=m + help + This option enables support for a netlink-based userspace interface + + config IP_NF_CT_PROTO_SCTP tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)' depends on IP_NF_CONNTRACK && EXPERIMENTAL @@ -774,11 +784,5 @@ config IP_NF_ARP_MANGLE Allows altering the ARP packet payload: source and destination hardware and network addresses. -config IP_NF_CONNTRACK_NETLINK - tristate 'Connection tracking netlink interface' - depends on IP_NF_CONNTRACK && NETFILTER_NETLINK - help - This option enables support for a netlink-based userspace interface - endmenu -- cgit v0.10.2 From 9eb0eec74d9425f4376df653304783339a027d79 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 17 Sep 2005 00:41:21 -0700 Subject: [NETFILTER] move nfnetlink options to right location in kconfig menu Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/Kconfig b/net/Kconfig index 2bdd562..60f6f32 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -140,6 +140,7 @@ config BRIDGE_NETFILTER If unsure, say N. +source "net/netfilter/Kconfig" source "net/ipv4/netfilter/Kconfig" source "net/ipv6/netfilter/Kconfig" source "net/decnet/netfilter/Kconfig" @@ -206,8 +207,6 @@ config NET_PKTGEN To compile this code as a module, choose M here: the module will be called pktgen. -source "net/netfilter/Kconfig" - endmenu endmenu -- cgit v0.10.2 From eb8edb085716621605cc2e7131a6369d2223d992 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 17 Sep 2005 00:42:26 -0700 Subject: [DCCP]: Add MAINTAINERS and CREDITS entries Also remove the SPX entry in MAINTAINERS, forgot to do that when I removed it. Signed-off-by: Ian McDonald Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/CREDITS b/CREDITS index f553f8c..a347520 100644 --- a/CREDITS +++ b/CREDITS @@ -2211,6 +2211,15 @@ D: OV511 driver S: (address available on request) S: USA +N: Ian McDonald +E: iam4@cs.waikato.ac.nz +E: imcdnzl@gmail.com +W: http://wand.net.nz/~iam4 +W: http://imcdnzl.blogspot.com +D: DCCP, CCID3 +S: Hamilton +S: New Zealand + N: Patrick McHardy E: kaber@trash.net P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80 @@ -2246,19 +2255,12 @@ S: D-90453 Nuernberg S: Germany N: Arnaldo Carvalho de Melo -E: acme@conectiva.com.br -E: acme@kernel.org -E: acme@gnu.org -W: http://bazar2.conectiva.com.br/~acme -W: http://advogato.org/person/acme +E: acme@mandriva.com +E: acme@ghostprotocols.net +W: http://oops.ghostprotocols.net:81/blog/ P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 -D: wanrouter hacking -D: misc Makefile, Config.in, drivers and network stacks fixes -D: IPX & LLC network stacks maintainer -D: Cyclom 2X synchronous card driver -D: wl3501 PCMCIA wireless card driver -D: i18n for minicom, net-tools, util-linux, fetchmail, etc -S: Conectiva S.A. +D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks +S: Mandriva S: R. Tocantins, 89 - Cristo Rei S: 80050-430 - Curitiba - Paraná S: Brazil diff --git a/MAINTAINERS b/MAINTAINERS index d1e0eb4..dc8f3ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -686,6 +686,13 @@ P: Guennadi Liakhovetski M: g.liakhovetski@gmx.de S: Maintained +DCCP PROTOCOL +P: Arnaldo Carvalho de Melo +M: acme@mandriva.com +L: dccp@vger.kernel.org +W: http://www.wlug.org.nz/DCCP +S: Maintained + DECnet NETWORK LAYER P: Patrick Caulfield M: patrick@tykepenguin.com @@ -2271,12 +2278,6 @@ M: R.E.Wolff@BitWizard.nl L: linux-kernel@vger.kernel.org ? S: Supported -SPX NETWORK LAYER -P: Jay Schulist -M: jschlst@samba.org -L: netdev@vger.kernel.org -S: Supported - SRM (Alpha) environment access P: Jan-Benedict Glaw M: jbglaw@lug-owl.de -- cgit v0.10.2 From c58ec93245a1fb7354f9e331960380827b9f41db Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 17 Sep 2005 00:46:27 -0700 Subject: [TG3]: Fix 4GB boundary tx handling Fix and simplify the workaround code for the 4GB boundary tx buffer hardware bug. 1. Need to unmap the original SKB's dma addresses if a new SKB cannot be allocated. 2. Need to pass the base flag to tigon3_4gb_hwbug_workaround() or TSO won't work properly. 3. The guilty entry and length parameters for tigon3_4gb_hwbug_workaround() are removed as they are not necessary. 4. Remove assumption that only one fragment can hit the 4GB boundary. Another fragment can hit 8GB for example. Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 06b02c5..81f4aed 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev) schedule_work(&tp->reset_task); } +/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */ +static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) +{ + u32 base = (u32) mapping & 0xffffffff; + + return ((base > 0xffffdcc0) && + (base + len + 8 < base)); +} + static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, - u32 guilty_entry, int guilty_len, - u32 last_plus_one, u32 *start, u32 mss) + u32 last_plus_one, u32 *start, + u32 base_flags, u32 mss) { struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); - dma_addr_t new_addr; + dma_addr_t new_addr = 0; u32 entry = *start; - int i; + int i, ret = 0; if (!new_skb) { - dev_kfree_skb(skb); - return -1; + ret = -1; + } else { + /* New SKB is guaranteed to be linear. */ + entry = *start; + new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, + PCI_DMA_TODEVICE); + /* Make sure new skb does not cross any 4G boundaries. + * Drop the packet if it does. + */ + if (tg3_4g_overflow_test(new_addr, new_skb->len)) { + ret = -1; + dev_kfree_skb(new_skb); + new_skb = NULL; + } else { + tg3_set_txd(tp, entry, new_addr, new_skb->len, + base_flags, 1 | (mss << 1)); + *start = NEXT_TX(entry); + } } - /* New SKB is guaranteed to be linear. */ - entry = *start; - new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, - PCI_DMA_TODEVICE); - tg3_set_txd(tp, entry, new_addr, new_skb->len, - (skb->ip_summed == CHECKSUM_HW) ? - TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1)); - *start = NEXT_TX(entry); - /* Now clean up the sw ring entries. */ i = 0; while (entry != last_plus_one) { @@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, dev_kfree_skb(skb); - return 0; + return ret; } static void tg3_set_txd(struct tg3 *tp, int entry, @@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry, txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; } -static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) -{ - u32 base = (u32) mapping & 0xffffffff; - - return ((base > 0xffffdcc0) && - (base + len + 8 < base)); -} - static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; - unsigned int i; u32 len, entry, base_flags, mss; int would_hit_hwbug; @@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) would_hit_hwbug = 0; if (tg3_4g_overflow_test(mapping, len)) - would_hit_hwbug = entry + 1; + would_hit_hwbug = 1; tg3_set_txd(tp, entry, mapping, len, base_flags, (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); @@ -3648,12 +3655,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->tx_buffers[entry].skb = NULL; pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); - if (tg3_4g_overflow_test(mapping, len)) { - /* Only one should match. */ - if (would_hit_hwbug) - BUG(); - would_hit_hwbug = entry + 1; - } + if (tg3_4g_overflow_test(mapping, len)) + would_hit_hwbug = 1; if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tg3_set_txd(tp, entry, mapping, len, @@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (would_hit_hwbug) { u32 last_plus_one = entry; u32 start; - unsigned int len = 0; - - would_hit_hwbug -= 1; - entry = entry - 1 - skb_shinfo(skb)->nr_frags; - entry &= (TG3_TX_RING_SIZE - 1); - start = entry; - i = 0; - while (entry != last_plus_one) { - if (i == 0) - len = skb_headlen(skb); - else - len = skb_shinfo(skb)->frags[i-1].size; - - if (entry == would_hit_hwbug) - break; - i++; - entry = NEXT_TX(entry); - - } + start = entry - 1 - skb_shinfo(skb)->nr_frags; + start &= (TG3_TX_RING_SIZE - 1); /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ - if (tigon3_4gb_hwbug_workaround(tp, skb, - entry, len, - last_plus_one, - &start, mss)) + if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one, + &start, base_flags, mss)) goto out_unlock; entry = start; -- cgit v0.10.2 From d7e70ba45fd9850296ebb78ff5827f6a375f650c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 16 Sep 2005 19:27:29 -0700 Subject: [PATCH] RAID6 Altivec fix This patch fixes a signedness bug with RAID6 for Altivec, and makes the Altivec code testable in userspace. Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h index f80ee63..31cbee7 100644 --- a/drivers/md/raid6.h +++ b/drivers/md/raid6.h @@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; #define __init #define __exit #define __attribute_const__ __attribute__((const)) +#define noinline __attribute__((noinline)) #define preempt_enable() #define preempt_disable() +#define cpu_has_feature(x) 1 +#define enable_kernel_altivec() +#define disable_kernel_altivec() #endif /* __KERNEL__ */ diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index acf386f..51c63c0 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c @@ -19,6 +19,7 @@ #include "raid6.h" #ifndef __KERNEL__ #include +#include #endif struct raid6_calls raid6_call; diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc index 1de8f03..b9afd35 100644 --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc @@ -27,16 +27,20 @@ #ifdef CONFIG_ALTIVEC #include -#include -#include +#ifdef __KERNEL__ +# include +# include +#endif /* - * This is the C data type to use + * This is the C data type to use. We use a vector of + * signed char so vec_cmpgt() will generate the right + * instruction. */ -typedef vector unsigned char unative_t; +typedef vector signed char unative_t; -#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) +#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) #define NSIZE sizeof(unative_t) /* @@ -108,7 +112,11 @@ int raid6_have_altivec(void); int raid6_have_altivec(void) { /* This assumes either all CPUs have Altivec or none does */ +# ifdef __KERNEL__ return cpu_has_feature(CPU_FTR_ALTIVEC); +# else + return 1; +# endif } #endif diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile index 5578067..78e0396 100644 --- a/drivers/md/raid6test/Makefile +++ b/drivers/md/raid6test/Makefile @@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired CFLAGS = -I.. -g $(OPTFLAGS) LD = ld PERL = perl +AR = ar +RANLIB = ranlib .c.o: $(CC) $(CFLAGS) -c -o $@ $< @@ -18,18 +20,33 @@ PERL = perl %.uc: ../%.uc cp -f $< $@ -all: raid6.o raid6test +all: raid6.a raid6test -raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ +raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ raid6int32.o \ raid6mmx.o raid6sse1.o raid6sse2.o \ + raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \ raid6recov.o raid6algos.o \ raid6tables.o - $(LD) -r -o $@ $^ + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ -raid6test: raid6.o test.c +raid6test: test.c raid6.a $(CC) $(CFLAGS) -o raid6test $^ +raid6altivec1.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@ + +raid6altivec2.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@ + +raid6altivec4.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@ + +raid6altivec8.c: raid6altivec.uc ../unroll.pl + $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@ + raid6int1.c: raid6int.uc ../unroll.pl $(PERL) ../unroll.pl 1 < raid6int.uc > $@ @@ -52,7 +69,7 @@ raid6tables.c: mktables ./mktables > raid6tables.c clean: - rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test + rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test spotless: clean rm -f *~ -- cgit v0.10.2 From 12e8780813c8c515b685b86c1306d169a4cae5fe Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 16 Sep 2005 19:27:30 -0700 Subject: [PATCH] SharpSL: Add missing hunk from backlight update This hunk from the sharpsl/corgi backlight update appears to have got lost somewhere along the way. Its needed to match the other changes. Signed-Off-By: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index a328176..630f2df 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -19,17 +19,18 @@ #include #include -#include -#include +#include +#include -#define CORGI_MAX_INTENSITY 0x3e #define CORGI_DEFAULT_INTENSITY 0x1f -#define CORGI_LIMIT_MASK 0x0b +#define CORGI_LIMIT_MASK 0x0b static int corgibl_powermode = FB_BLANK_UNBLANK; static int current_intensity = 0; static int corgibl_limit = 0; +static void (*corgibl_mach_set_intensity)(int intensity); static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static struct backlight_properties corgibl_data; static void corgibl_send_intensity(int intensity) { -- cgit v0.10.2 From 62052d42a5327281fc43fd7bcfb73ac7d36ffc2e Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 16 Sep 2005 19:27:31 -0700 Subject: [PATCH] MTD: Update SharpSL partition definitions Add partition definitions for the new Sharp Zaurus models Spitz (SL-C3000), Akita (SL-C1000) and Borzoi (SL-C3100) Signed-off-by: Richard Purdie Signed-off-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index d15da6f..b7f093f 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c @@ -82,7 +82,7 @@ int __init init_sharpsl(void) } else if (machine_is_tosa()) { sharpsl_partitions[0].size=0x006a0000; sharpsl_partitions[0].offset=0x00160000; - } else if (machine_is_spitz()) { + } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) { sharpsl_partitions[0].size=0x006b0000; sharpsl_partitions[0].offset=0x00140000; } else { diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 9853b87..88b5b5b 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -221,10 +221,16 @@ sharpsl_nand_init(void) sharpsl_partition_info[1].size=25 * 1024 * 1024; } else if (machine_is_husky()) { sharpsl_partition_info[1].size=53 * 1024 * 1024; - } + } else if (machine_is_spitz()) { + sharpsl_partition_info[1].size=5 * 1024 * 1024; + } else if (machine_is_akita()) { + sharpsl_partition_info[1].size=58 * 1024 * 1024; + } else if (machine_is_borzoi()) { + sharpsl_partition_info[1].size=32 * 1024 * 1024; + } } - if (machine_is_husky()) { + if (machine_is_husky() || machine_is_borzoi()) { /* Need to use small eraseblock size for backward compatibility */ sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; } -- cgit v0.10.2 From 1306a2b2be35179449db737ac0562b067cb96ddb Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 16 Sep 2005 19:27:32 -0700 Subject: [PATCH] s390: default configuration Update default configuration of s390. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0865251..45d44c6 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc4 -# Fri Jul 29 14:49:30 2005 +# Linux kernel version: 2.6.14-rc1 +# Wed Sep 14 16:46:19 2005 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -21,6 +21,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -33,6 +34,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -94,6 +96,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # # I/O subsystem configuration @@ -151,8 +154,8 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -CONFIG_IP_TCPDIAG_IPV6=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y CONFIG_IPV6=y @@ -165,6 +168,11 @@ CONFIG_IPV6=y # CONFIG_NETFILTER is not set # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -217,9 +225,11 @@ CONFIG_NET_CLS_POLICE=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETFILTER_NETLINK is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # CONFIG_PCMCIA is not set # @@ -233,6 +243,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -260,6 +271,7 @@ CONFIG_SCSI_LOGGING=y # CONFIG_SCSI_SPI_ATTRS is not set CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -280,7 +292,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -384,6 +395,10 @@ CONFIG_EQUALIZER=m CONFIG_TUN=m # +# PHY device support +# + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -453,10 +468,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -465,6 +476,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -485,11 +497,10 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -533,6 +544,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -572,6 +584,7 @@ CONFIG_MSDOS_PARTITION=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y @@ -626,5 +639,6 @@ CONFIG_CRYPTO=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=m # CONFIG_LIBCRC32C is not set -- cgit v0.10.2 From d176795b3eedc18f95160ecc0d7cdf0d2bc5a578 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 16 Sep 2005 19:27:33 -0700 Subject: [PATCH] s390: bl_dev array size Calculate correct size for bl_dev array. It should be 8KB instead of 512KB for 2^16 bits. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index aac83ce..a1c52a6 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.34 $ + * $Revision: 1.35 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -35,7 +35,7 @@ */ /* 65536 bits to indicate if a devno is blacklisted or not */ -#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \ +#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \ (8*sizeof(long))) static unsigned long bl_dev[__BL_DEV_WORDS]; typedef enum {add, free} range_action; -- cgit v0.10.2 From 90f4e12112284f1a41594e2950e6eced5b064efc Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 16 Sep 2005 19:27:34 -0700 Subject: [PATCH] s390: crypto driver patch take 2 Got confused with the crypto update. The last patch added a call to destroy_workqueue() for a non-existent workqueue with the comment "Remove device workqueue on module unload". This is nonsense. Remove the offending hunk again. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 6aeef3b..0cb47ec 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -682,9 +682,6 @@ z90crypt_cleanup_module(void) del_timer(&config_timer); del_timer(&cleanup_timer); - if (z90_device_work) - destroy_workqueue(z90_device_work); - destroy_z90crypt(); PRINTKN("Unloaded.\n"); -- cgit v0.10.2 From b7ae9dd80a3ecf070ea0c5fe1d405cd7687d6c51 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 16 Sep 2005 19:27:34 -0700 Subject: [PATCH] s390: show_cpuinfo fix Disable preemption in show_cpuinfo to avoid problems and the warning about smp_processor_id. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5ba5a54..907d16a 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -634,6 +634,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) struct cpuinfo_S390 *cpuinfo; unsigned long n = (unsigned long) v - 1; + preempt_disable(); if (!n) { seq_printf(m, "vendor_id : IBM/S390\n" "# processors : %i\n" @@ -658,6 +659,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpuinfo->cpu_id.ident, cpuinfo->cpu_id.machine); } + preempt_enable(); return 0; } -- cgit v0.10.2 From c782268be8892962a1ae2c09a2e87e7849454ef1 Mon Sep 17 00:00:00 2001 From: Volker Sameske Date: Fri, 16 Sep 2005 19:27:35 -0700 Subject: [PATCH] s390: diag 0x308 reipl Add code to support the re-IPL method using diagnose 0x308. Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index ab1e49d2..8584dd8 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o profile.o irq.o + semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o extra-$(CONFIG_ARCH_S390_31) += head.o extra-$(CONFIG_ARCH_S390X) += head64.o diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c new file mode 100644 index 0000000..83cb42b --- /dev/null +++ b/arch/s390/kernel/reipl_diag.c @@ -0,0 +1,39 @@ +/* + * This file contains the implementation of the + * Linux re-IPL support + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Volker Sameske (sameske@de.ibm.com) + * + */ + +#include + +static unsigned int reipl_diag_rc1; +static unsigned int reipl_diag_rc2; + +/* + * re-IPL the system using the last used IPL parameters + */ +void reipl_diag(void) +{ + asm volatile ( + " la %%r4,0\n" + " la %%r5,0\n" + " diag %%r4,%2,0x308\n" + "0:\n" + " st %%r4,%0\n" + " st %%r5,%1\n" + ".section __ex_table,\"a\"\n" +#ifdef __s390x__ + " .align 8\n" + " .quad 0b, 0b\n" +#else + " .align 4\n" + " .long 0b, 0b\n" +#endif + ".previous\n" + : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2) + : "d" (3) : "cc", "4", "5" ); +} diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 907d16a..5204778 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -261,8 +261,11 @@ void (*_machine_power_off)(void) = machine_power_off_smp; * Reboot, halt and power_off routines for non SMP. */ extern void reipl(unsigned long devno); +extern void reipl_diag(void); static void do_machine_restart_nonsmp(char * __unused) { + reipl_diag(); + if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0); else diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 85222fe..e13c87b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -65,6 +65,7 @@ extern char vmhalt_cmd[]; extern char vmpoff_cmd[]; extern void reipl(unsigned long devno); +extern void reipl_diag(void); static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); @@ -283,6 +284,8 @@ static void do_machine_restart(void * __unused) * interrupted by an external interrupt and s390irq * locks are always held disabled). */ + reipl_diag(); + if (MACHINE_IS_VM) cpcmd ("IPL", NULL, 0, NULL); else -- cgit v0.10.2 From fa72e26a640e551637f91122d782d5a85d514f5b Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Fri, 16 Sep 2005 19:27:36 -0700 Subject: [PATCH] Remove arch/arm26/boot/compressed/hw-bse.c Remove nowhere referenced file (egrep "hw-bse\." didn't find anything). Signed-off-by: Domen Puncer Signed-off-by: Alexey Dobriyan Acked-by: Ian Molton Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c deleted file mode 100644 index 3e8f07f..0000000 --- a/arch/arm26/boot/compressed/hw-bse.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Bright Star Engineering Inc. - * - * code for readng parameters from the - * parameter blocks of the boot block - * flash memory - * - */ - -static int strcmp(const char *s1, const char *s2) -{ - while (*s1 != '\0' && *s1 == *s2) - { - s1++; - s2++; - } - - return (*(unsigned char *) s1) - (*(unsigned char *) s2); -} - -struct pblk_t { - char type; - unsigned short size; -}; - -static char *bse_getflashparam(char *name) { - unsigned int esize; - char *q,*r; - unsigned char *p,*e; - struct pblk_t *thepb = (struct pblk_t *) 0x00004000; - struct pblk_t *altpb = (struct pblk_t *) 0x00006000; - if (thepb->type&1) { - if (altpb->type&1) { - /* no valid param block */ - return (char*)0; - } else { - /* altpb is valid */ - struct pblk_t *tmp; - tmp = thepb; - thepb = altpb; - altpb = tmp; - } - } - p = (char*)thepb + sizeof(struct pblk_t); - e = p + thepb->size; - while (p < e) { - q = p; - esize = *p; - if (esize == 0xFF) break; - if (esize == 0) break; - if (esize > 127) { - esize = (esize&0x7F)<<8 | p[1]; - q++; - } - q++; - r=q; - if (*r && ((name == 0) || (!strcmp(name,r)))) { - while (*q++) ; - return q; - } - p+=esize; - } - return (char*)0; -} - -void bse_setup(void) { - /* extract the linux cmdline from flash */ - char *name=bse_getflashparam("linuxboot"); - char *x = (char *)0xc0000100; - if (name) { - while (*name) *x++=*name++; - } - *x=0; -} -- cgit v0.10.2 From 26ff6ad9786abf6f40a6d3cbb89753b4fa50cb00 Mon Sep 17 00:00:00 2001 From: Srivatsa Vaddagiri Date: Fri, 16 Sep 2005 19:27:40 -0700 Subject: [PATCH] CPU hotplug breaks wake_up_new_task Fix a problem wherein a new-born task is added to a dead CPU. Signed-off-by: Srivatsa Vaddagiri Acked-by: Nick Piggin Acked-by: Shaohua Li Acked-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 8149f36..533ce27 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1062,7 +1062,8 @@ static task_t *copy_process(unsigned long clone_flags, * parent's CPU). This avoids alot of nasty races. */ p->cpus_allowed = current->cpus_allowed; - if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed))) + if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || + !cpu_online(task_cpu(p)))) set_task_cpu(p, smp_processor_id()); /* -- cgit v0.10.2 From 6add9f7f529b124938d14ae9db5a952d1272075a Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 16 Sep 2005 19:27:42 -0700 Subject: [PATCH] s390: kernel stack corruption When an asynchronous interruption occurs during the execution of the 'critical section' within the generic interruption handling code (entry.S), a faulty check for a userspace PSW may result in a corrupted kernel stack pointer which subsequently triggers a stack overflow check. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 58fc7fb..9b30f4c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -108,7 +108,7 @@ STACK_SIZE = 1 << STACK_SHIFT bl BASED(0f) l %r14,BASED(.Lcleanup_critical) basr %r14,%r14 - tm 0(%r12),0x01 # retest problem state after cleanup + tm 1(%r12),0x01 # retest problem state after cleanup bnz BASED(1f) 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? slr %r14,%r15 diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d0c9ffa..7b9b4a2 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -101,7 +101,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) clc \psworg+8(8),BASED(.Lcritical_start) jl 0f brasl %r14,cleanup_critical - tm 0(%r12),0x01 # retest problem state after cleanup + tm 1(%r12),0x01 # retest problem state after cleanup jnz 1f 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? slgr %r14,%r15 -- cgit v0.10.2 From f6e34c6af6f18bd6c66bfb1c6a7c57068412aa73 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:43 -0700 Subject: [PATCH] uml: _switch_to code consolidation This patch moves code that is in both switch_to_tt and switch_to_skas to the top level _switch_to function, keeping us from duplicating code. It is required for the stack trace patch to work properly. Signed-off-by: Allan Graves Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index c23d8a0..1143f5e 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -113,8 +113,16 @@ void set_current(void *t) void *_switch_to(void *prev, void *next, void *last) { - return(CHOOSE_MODE(switch_to_tt(prev, next), - switch_to_skas(prev, next))); + struct task_struct *from = prev; + struct task_struct *to= next; + + to->thread.prev_sched = from; + set_current(to); + + CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + + return(current->thread.prev_sched); + } void interrupt_end(void) diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h index e484900..c97a80d 100644 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ b/arch/um/kernel/skas/include/mode_kern-skas.h @@ -11,7 +11,7 @@ #include "asm/ptrace.h" extern void flush_thread_skas(void); -extern void *switch_to_skas(void *prev, void *next); +extern void switch_to_skas(void *prev, void *next); extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, unsigned long esp); extern int copy_thread_skas(int nr, unsigned long clone_flags, diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 3d1b227..efe92e8 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -24,7 +24,7 @@ #include "proc_mm.h" #include "registers.h" -void *switch_to_skas(void *prev, void *next) +void switch_to_skas(void *prev, void *next) { struct task_struct *from, *to; @@ -35,16 +35,11 @@ void *switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - to->thread.prev_sched = from; - set_current(to); - switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); if(current->pid == 0) switch_timers(1); - - return(current->thread.prev_sched); } extern void schedule_tail(struct task_struct *prev); diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h index e0ca0e0..2a35b15 100644 --- a/arch/um/kernel/tt/include/mode_kern-tt.h +++ b/arch/um/kernel/tt/include/mode_kern-tt.h @@ -11,7 +11,7 @@ #include "asm/ptrace.h" #include "asm/uaccess.h" -extern void *switch_to_tt(void *prev, void *next); +extern void switch_to_tt(void *prev, void *next); extern void flush_thread_tt(void); extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, unsigned long esp); diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index a189a2b..0de05a268 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -26,7 +26,7 @@ #include "init.h" #include "tt.h" -void *switch_to_tt(void *prev, void *next, void *last) +int switch_to_tt(void *prev, void *next, void *last) { struct task_struct *from, *to, *prev_sched; unsigned long flags; @@ -36,8 +36,6 @@ void *switch_to_tt(void *prev, void *next, void *last) from = prev; to = next; - to->thread.prev_sched = from; - cpu = from->thread_info->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); @@ -53,7 +51,6 @@ void *switch_to_tt(void *prev, void *next, void *last) forward_pending_sigio(to->thread.mode.tt.extern_pid); c = 0; - set_current(to); err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) @@ -85,8 +82,6 @@ void *switch_to_tt(void *prev, void *next, void *last) flush_tlb_all(); local_irq_restore(flags); - - return(current->thread.prev_sched); } void release_thread_tt(struct task_struct *task) -- cgit v0.10.2 From 3eddddcf239c89bbd3c50d1440001a3d384ed40a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:46 -0700 Subject: [PATCH] uml: breakpoint an arbitrary thread This patch implements a stack trace for a thread, not unlike sysrq-t does. The advantage to this is that a break point can be placed on showreqs, so that upon showing the stack, you jump immediately into the debugger. While sysrq-t does the same thing, sysrq-t shows *all* threads stacks. It also doesn't work right now. In the future, I thought it might be acceptable to make this show all pids stacks, but perhaps leaving well enough alone and just using sysrq-t would be okay. For now, upon receiving the stack command, UML switches context to that thread, dumps its registers, and then switches context back to the original thread. Since UML compacts all threads into one of 4 host threads, this sort of mechanism could be expanded in the future to include other debugging helpers that sysrq does not cover. Note by jdike - The main benefit to this is that it brings an arbitrary thread back into context, where it can be examined by gdb. The fact that it dumps it stack is secondary. This provides the capability to examine a sleeping thread, which has existed in tt mode, but not in skas mode until now. Also, the other threads, that sysrq doesn't cover, can be gdb-ed directly anyway. Signed-off-by: Allan Graves Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index c190c24..12c9536 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -32,6 +32,7 @@ #include "os.h" #include "umid.h" #include "irq_kern.h" +#include "choose-mode.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) @@ -276,6 +277,7 @@ void mconsole_proc(struct mc_request *req) go - continue the UML after a 'stop' \n\ log - make UML enter into the kernel log\n\ proc - returns the contents of the UML's /proc/\n\ + stack - returns the stack of the specified pid\n\ " void mconsole_help(struct mc_request *req) @@ -479,6 +481,56 @@ void mconsole_sysrq(struct mc_request *req) } #endif +/* Mconsole stack trace + * Added by Allan Graves, Jeff Dike + * Dumps a stacks registers to the linux console. + * Usage stack . + */ +void do_stack(struct mc_request *req) +{ + char *ptr = req->request.data; + int pid_requested= -1; + struct task_struct *from = NULL; + struct task_struct *to = NULL; + + /* Would be nice: + * 1) Send showregs output to mconsole. + * 2) Add a way to stack dump all pids. + */ + + ptr += strlen("stack"); + while(isspace(*ptr)) ptr++; + + /* Should really check for multiple pids or reject bad args here */ + /* What do the arguments in mconsole_reply mean? */ + if(sscanf(ptr, "%d", &pid_requested) == 0){ + mconsole_reply(req, "Please specify a pid", 1, 0); + return; + } + + from = current; + to = find_task_by_pid(pid_requested); + + if((to == NULL) || (pid_requested == 0)) { + mconsole_reply(req, "Couldn't find that pid", 1, 0); + return; + } + to->thread.saved_task = current; + + switch_to(from, to, from); + mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); +} + +void mconsole_stack(struct mc_request *req) +{ + /* This command doesn't work in TT mode, so let's check and then + * get out of here + */ + CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", + 1, 0), + do_stack(req)); +} + /* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index fe5afb132..a5b8aea 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -30,6 +30,7 @@ static struct mconsole_command commands[] = { { "go", mconsole_go, MCONSOLE_INTR }, { "log", mconsole_log, MCONSOLE_INTR }, { "proc", mconsole_proc, MCONSOLE_PROC }, + { "stack", mconsole_stack, MCONSOLE_INTR }, }; /* Initialized in mconsole_init, which is an initcall */ diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index cfa368e..b1b512f 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h @@ -81,6 +81,7 @@ extern void mconsole_stop(struct mc_request *req); extern void mconsole_go(struct mc_request *req); extern void mconsole_log(struct mc_request *req); extern void mconsole_proc(struct mc_request *req); +extern void mconsole_stack(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 1143f5e..39cf568 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -119,7 +119,14 @@ void *_switch_to(void *prev, void *next, void *last) to->thread.prev_sched = from; set_current(to); - CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + do { + current->thread.saved_task = NULL ; + CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); + if(current->thread.saved_task) + show_regs(&(current->thread.regs)); + next= current->thread.saved_task; + prev= current; + } while(current->thread.saved_task); return(current->thread.prev_sched); diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index b2fc94f..2d24236 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h @@ -21,6 +21,7 @@ struct thread_struct { * copy_thread) to mark that we are begin called from userspace (fork / * vfork / clone), and reset to 0 after. It is left to 0 when called * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */ + struct task_struct *saved_task; int forking; int nsyscalls; struct pt_regs regs; -- cgit v0.10.2 From edcc2205d33d6baefc773c915b6e7ce517bc0b19 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:47 -0700 Subject: [PATCH] uml: Remove an unused file This removes a file which is no longer used. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c deleted file mode 100644 index b94d2bc4f..0000000 --- a/arch/um/drivers/ubd_user.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "asm/types.h" -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "ubd_user.h" -#include "os.h" -#include "cow.h" - -#include -#include - -void ignore_sigwinch_sig(void) -{ - signal(SIGWINCH, SIG_IGN); -} - -int start_io_thread(unsigned long sp, int *fd_out) -{ - int pid, fds[2], err; - - err = os_pipe(fds, 1, 1); - if(err < 0){ - printk("start_io_thread - os_pipe failed, err = %d\n", -err); - goto out; - } - - kernel_fd = fds[0]; - *fd_out = fds[1]; - - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, - NULL); - if(pid < 0){ - printk("start_io_thread - clone failed : errno = %d\n", errno); - err = -errno; - goto out_close; - } - - return(pid); - - out_close: - os_close_file(fds[0]); - os_close_file(fds[1]); - kernel_fd = -1; - *fd_out = -1; - out: - return(err); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v0.10.2 From d9f0d9151083a9a77331a020a7fee498cf828e3b Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:47 -0700 Subject: [PATCH] uml: Remove a useless include linux/inet.h isn't needed, and on my system, is empty. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 7a0d115..3fd69067 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include -- cgit v0.10.2 From 64b7673f91c0c3614028c5942b0d6a91d0b64a98 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:48 -0700 Subject: [PATCH] uml: Remove some build warnings These ugly double-casts are the result of gdb complaining about size Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index b04897c..182905b 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -142,7 +142,7 @@ static int aio_thread(void *arg) "errno = %d\n", errno); } else { - aio = (struct aio_context *) event.data; + aio = (struct aio_context *) (long) event.data; if(update_aio(aio, event.res)){ do_aio(ctx, aio); continue; diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 1399520..5c02e33 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -9,6 +9,7 @@ */ #include #include +#include #include "init.h" #include "elf_user.h" #include "mem_user.h" @@ -54,7 +55,8 @@ __init void scan_elf_aux( char **envp) * a_un, so we have to use a_val, which is * all that's left. */ - elf_aux_platform = (char *) auxv->a_un.a_val; + elf_aux_platform = + (char *) (long) auxv->a_un.a_val; break; case AT_PAGESZ: page_size = auxv->a_un.a_val; -- cgit v0.10.2 From b4fd310e163477236a241580b3b8c29aee65f4cc Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:49 -0700 Subject: [PATCH] uml: preserve errno in error paths The poster child for this patch is the third tuntap_user hunk. When an ioctl fails, it properly closes the opened file descriptor and returns. However, the close resets errno to 0, and the 'return errno' that follows returns 0 rather than the value that ioctl set. This caused the caller to believe that the device open succeeded and had opened file descriptor 0, which caused no end of interesting behavior. The rest of this patch is a pass through the UML sources looking for places where errno could be reset before being passed back out. A common culprit is printk, which could call write, being called before errno is returned. In some cases, where the code ends up being much smaller, I just deleted the printk. There was another case where a caller of run_helper looked at errno after a failure, rather than the return value of run_helper, which was the errno value that it wanted. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 3fd69067..5db136e 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -54,7 +54,7 @@ static int mcast_open(void *data) struct mcast_data *pri = data; struct sockaddr_in *sin = pri->mcast_addr; struct ip_mreq mreq; - int fd = -EINVAL, yes = 1, err = -EINVAL;; + int fd, yes = 1, err = 0; if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) @@ -65,13 +65,14 @@ static int mcast_open(void *data) if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); - fd = -errno; + err = -errno; goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -80,6 +81,7 @@ static int mcast_open(void *data) sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); + err = -errno; goto out_close; } @@ -87,12 +89,14 @@ static int mcast_open(void *data) if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); + err = -errno; goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); + err = -errno; goto out_close; } @@ -107,14 +111,15 @@ static int mcast_open(void *data) "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); + err = -errno; goto out_close; } - out: return fd; out_close: os_close_file(fd); + out: return err; } diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index a5b8aea..310c1f8 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -173,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) if(notify_sock < 0){ notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); if(notify_sock < 0){ - printk("mconsole_notify - socket failed, errno = %d\n", - errno); err = -errno; + printk("mconsole_notify - socket failed, errno = %d\n", + err); } } unlock_notify(); @@ -198,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, sizeof(target)); if(n < 0){ - printk("mconsole_notify - sendto failed, errno = %d\n", errno); err = -errno; + printk("mconsole_notify - sendto failed, errno = %d\n", errno); } return(err); } diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index ed84d01..0306a1b 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d, fd = get_pty(); if(fd < 0){ + err = -errno; printk("open_pts : Failed to open pts\n"); - return(-errno); + return err; } if(data->raw){ CATCH_EINTR(err = tcgetattr(fd, &data->tt)); diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 93dc191..90e0e5f 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d, fd = mkstemp(file); if(fd < 0){ + err = -errno; printk("xterm_open : mkstemp failed, errno = %d\n", errno); - return(-errno); + return err; } if(unlink(file)){ + err = -errno; printk("xterm_open : unlink failed, errno = %d\n", errno); - return(-errno); + return err; } os_close_file(fd); diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index f83e1e8..33fb0bd 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c @@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, data.fd = fds[1]; pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ - printk("run_helper : clone failed, errno = %d\n", errno); ret = -errno; + printk("run_helper : clone failed, errno = %d\n", errno); goto out_close; } @@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long *stack_out, int stack_order) { unsigned long stack, sp; - int pid, status; + int pid, status, err; stack = alloc_stack(stack_order, um_in_interrupt()); if(stack == 0) return(-ENOMEM); @@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, sp = stack + (page_size() << stack_order) - sizeof(void *); pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); if(pid < 0){ + err = -errno; printk("run_helper_thread : clone failed, errno = %d\n", errno); - return(-errno); + return err; } if(stack_out == NULL){ CATCH_EINTR(pid = waitpid(pid, &status, 0)); if(pid < 0){ + err = -errno; printk("run_helper_thread - wait failed, errno = %d\n", errno); - pid = -errno; + pid = err; } if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " @@ -156,8 +158,8 @@ int helper_wait(int pid) CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); if(ret < 0){ + ret = -errno; printk("helper_wait : waitpid failed, errno = %d\n", errno); - return(-errno); } return(ret); } diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 954ff67..a25f3ea 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -109,18 +109,14 @@ int raw(int fd) int err; CATCH_EINTR(err = tcgetattr(fd, &tt)); - if (err < 0) { - printk("tcgetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; cfmakeraw(&tt); CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); - if (err < 0) { - printk("tcsetattr failed, errno = %d\n", errno); - return(-errno); - } + if(err < 0) + return -errno; /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 182905b..e942beb 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -313,15 +313,16 @@ static int init_aio_26(void) int err; if(io_setup(256, &ctx)){ + err = -errno; printk("aio_thread failed to initialize context, err = %d\n", errno); - return -errno; + return err; } err = run_helper_thread(aio_thread, NULL, CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); if(err < 0) - return -errno; + return err; aio_pid = err; diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 4b83c6c..4ba9b17 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov; - int pid, n; + int pid, n, err; sprintf(version_buf, "%d", UML_NET_VERSION); @@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, n = recvmsg(me, &msg, 0); *used_out = n; if(n < 0){ + err = -errno; printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", errno); - return(-errno); + return err; } CATCH_EINTR(waitpid(pid, NULL, 0)); @@ -147,9 +148,10 @@ static int tuntap_open(void *data) ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ + err = -errno; printk("TUNSETIFF failed, errno = %d\n", errno); os_close_file(pri->fd); - return(-errno); + return err; } } else { diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index fd45bb2..f55773c 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols) int os_new_tty_pgrp(int fd, int pid) { - if(ioctl(fd, TIOCSCTTY, 0) < 0){ - printk("TIOCSCTTY failed, errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSCTTY, 0) < 0) + return -errno; - if(tcsetpgrp(fd, pid) < 0){ - printk("tcsetpgrp failed, errno = %d\n", errno); - return(-errno); - } + if(tcsetpgrp(fd, pid) < 0) + return -errno; return(0); } @@ -146,18 +142,12 @@ int os_set_slip(int fd) int disc, sencap; disc = N_SLIP; - if(ioctl(fd, TIOCSETD, &disc) < 0){ - printk("Failed to set slip line discipline - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, TIOCSETD, &disc) < 0) + return -errno; sencap = 0; - if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ - printk("Failed to set slip encapsulation - " - "errno = %d\n", errno); - return(-errno); - } + if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) + return -errno; return(0); } @@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave) int flags; flags = fcntl(master, F_GETFL); - if(flags < 0) { - printk("fcntl F_GETFL failed, errno = %d\n", errno); - return(-errno); - } + if(flags < 0) + return errno; if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)){ - printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", - errno); - return(-errno); - } + (fcntl(master, F_SETOWN, os_getpid()) < 0)) + return -errno; - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ - printk("fcntl F_SETFL failed, errno = %d\n", errno); - return(-errno); - } + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) + return -errno; return(0); } @@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out) int os_open_file(char *file, struct openflags flags, int mode) { - int fd, f = 0; + int fd, err, f = 0; if(flags.r && flags.w) f = O_RDWR; else if(flags.r) f = O_RDONLY; @@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode) return(-errno); if(flags.cl && fcntl(fd, F_SETFD, 1)){ + err = -errno; os_close_file(fd); - return(-errno); + return err; } return(fd); @@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out) return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ + err = -errno; printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - err = -errno; os_close_file(fd); return(err); } @@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec) int os_set_fd_async(int fd, int owner) { + int err; + /* XXX This should do F_GETFL first */ if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ + err = -errno; printk("os_set_fd_async : failed to set O_ASYNC and " "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); - return(-errno); + return err; } #ifdef notdef if(fcntl(fd, F_SETFD, 1) < 0){ @@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner) if((fcntl(fd, F_SETSIG, SIGIO) < 0) || (fcntl(fd, F_SETOWN, owner) < 0)){ + err = -errno; printk("os_set_fd_async : Failed to fcntl F_SETOWN " "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, owner, errno); - return(-errno); + return err; } return(0); @@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking) if(blocking) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flags) < 0){ - printk("Failed to change blocking on fd # %d, errno = %d\n", - fd, errno); - return(-errno); - } + if(fcntl(fd, F_SETFL, flags) < 0) + return -errno; + return(0); } @@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) int sock, err; sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (sock < 0){ - printk("create_unix_socket - socket failed, errno = %d\n", - errno); - return(-errno); - } + if(sock < 0) + return -errno; if(close_on_exec) { err = os_set_exec_close(sock, 1); @@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) snprintf(addr.sun_path, len, "%s", file); err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err < 0){ - printk("create_listening_socket at '%s' - bind failed, " - "errno = %d\n", file, errno); - return(-errno); - } + if(err < 0) + return -errno; return(sock); } -- cgit v0.10.2 From 0f80bc85c587e8fdeecece4f294a47eca4922ea2 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:50 -0700 Subject: [PATCH] uml: move libc code out of mem_user.c and tempfile.c The serial UML OS-abstraction layer patch (um/kernel dir). This moves all system calls from mem_user.c and tempfile.c files under os-Linux dir. Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index d6404bb..9fef412 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h @@ -51,7 +51,6 @@ extern unsigned long task_size; extern void check_devanon(void); extern int init_mem_user(void); -extern int create_mem_file(unsigned long len); extern void setup_memory(void *entry); extern unsigned long find_iomem(char *driver, unsigned long *len_out); extern int init_maps(unsigned long physmem, unsigned long iomem, @@ -64,20 +63,6 @@ extern unsigned long phys_offset(unsigned long phys); extern void unmap_physmem(void); extern void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x); -extern int protect_memory(unsigned long addr, unsigned long len, - int r, int w, int x, int must_succeed); extern unsigned long get_kmem_end(void); -extern void check_tmpexec(void); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 4c36245..583329d 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -157,6 +157,9 @@ extern int os_lock_file(int fd, int excl); extern void os_early_checks(void); extern int can_do_skas(void); +/* mem.c */ +extern int create_mem_file(unsigned long len); + /* process.c */ extern unsigned long os_process_pc(int pid); extern int os_process_parent(int pid); @@ -181,6 +184,8 @@ extern unsigned long long os_usecs(void); /* tt.c * for tt mode only (will be deleted in future...) */ +extern int protect_memory(unsigned long addr, unsigned long len, + int r, int w, int x, int must_succeed); extern void forward_pending_sigio(int target); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 614b8eb..7eb52c5 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -10,7 +10,7 @@ obj-y = config.o exec_kern.o exitcode.o \ helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \ - tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \ + time.o time_kern.o tlb.o trap_kern.o trap_user.o \ uaccess_user.o um_arch.o umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o @@ -24,8 +24,8 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \ - tty_log.o umid.o user_util.o +USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ + user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cd7c85b..49ed5dd 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c @@ -13,6 +13,7 @@ #include "asm/pgtable.h" #include "user_util.h" #include "mem_user.h" +#include "os.h" static struct fs_struct init_fs = INIT_FS; struct mm_struct init_mm = INIT_MM(init_mm); @@ -45,8 +46,8 @@ __attribute__((__section__(".data.init_task"))) = void unprotect_stack(unsigned long stack) { - protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, - 1, 1, 0, 1); + os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, + 1, 1, 0); } /* diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c index 4a663fd..d49640d 100644 --- a/arch/um/kernel/mem_user.c +++ b/arch/um/kernel/mem_user.c @@ -48,219 +48,16 @@ #include "tempfile.h" #include "kern_constants.h" -#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" - -static int create_tmp_file(unsigned long len) -{ - int fd, err; - char zero; - - fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); - if(fd < 0) { - os_print_error(fd, "make_tempfile"); - exit(1); - } - - err = os_mode_fd(fd, 0777); - if(err < 0){ - os_print_error(err, "os_mode_fd"); - exit(1); - } - err = os_seek_file(fd, len); - if(err < 0){ - os_print_error(err, "os_seek_file"); - exit(1); - } - zero = 0; - err = os_write_file(fd, &zero, 1); - if(err != 1){ - os_print_error(err, "os_write_file"); - exit(1); - } - - return(fd); -} - -void check_tmpexec(void) -{ - void *addr; - int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); - - addr = mmap(NULL, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); - printf("Checking PROT_EXEC mmap in /tmp..."); - fflush(stdout); - if(addr == MAP_FAILED){ - err = errno; - perror("failed"); - if(err == EPERM) - printf("/tmp must be not mounted noexec\n"); - exit(1); - } - printf("OK\n"); - munmap(addr, UM_KERN_PAGE_SIZE); - - os_close_file(fd); -} - -static int have_devanon = 0; - -void check_devanon(void) -{ - int fd; - - printk("Checking for /dev/anon on the host..."); - fd = open("/dev/anon", O_RDWR); - if(fd < 0){ - printk("Not available (open failed with errno %d)\n", errno); - return; - } - - printk("OK\n"); - have_devanon = 1; -} - -static int create_anon_file(unsigned long len) -{ - void *addr; - int fd; - - fd = open("/dev/anon", O_RDWR); - if(fd < 0) { - os_print_error(fd, "opening /dev/anon"); - exit(1); - } - - addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if(addr == MAP_FAILED){ - perror("mapping physmem file"); - exit(1); - } - munmap(addr, len); - - return(fd); -} - -int create_mem_file(unsigned long len) -{ - int err, fd; - - if(have_devanon) - fd = create_anon_file(len); - else fd = create_tmp_file(len); - - err = os_set_exec_close(fd, 1); - if(err < 0) - os_print_error(err, "exec_close"); - return(fd); -} - struct iomem_region *iomem_regions = NULL; int iomem_size = 0; -static int __init parse_iomem(char *str, int *add) -{ - struct iomem_region *new; - struct uml_stat buf; - char *file, *driver; - int fd, err, size; - - driver = str; - file = strchr(str,','); - if(file == NULL){ - printf("parse_iomem : failed to parse iomem\n"); - goto out; - } - *file = '\0'; - file++; - fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); - if(fd < 0){ - os_print_error(fd, "parse_iomem - Couldn't open io file"); - goto out; - } - - err = os_stat_fd(fd, &buf); - if(err < 0){ - os_print_error(err, "parse_iomem - cannot stat_fd file"); - goto out_close; - } - - new = malloc(sizeof(*new)); - if(new == NULL){ - perror("Couldn't allocate iomem_region struct"); - goto out_close; - } - - size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); - - *new = ((struct iomem_region) { .next = iomem_regions, - .driver = driver, - .fd = fd, - .size = size, - .phys = 0, - .virt = 0 }); - iomem_regions = new; - iomem_size += new->size + UM_KERN_PAGE_SIZE; - - return(0); - out_close: - os_close_file(fd); - out: - return(1); -} +extern int parse_iomem(char *str, int *add) __init; __uml_setup("iomem=", parse_iomem, "iomem=,\n" " Configure as an IO memory region named .\n\n" ); -int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, - int must_succeed) -{ - int err; - - err = os_protect_memory((void *) addr, len, r, w, x); - if(err < 0){ - if(must_succeed) - panic("protect failed, err = %d", -err); - else return(err); - } - return(0); -} - -#if 0 -/* Debugging facility for dumping stuff out to the host, avoiding the timing - * problems that come with printf and breakpoints. - * Enable in case of emergency. - */ - -int logging = 1; -int logging_fd = -1; - -int logging_line = 0; -char logging_buf[512]; - -void log(char *fmt, ...) -{ - va_list ap; - struct timeval tv; - struct openflags flags; - - if(logging == 0) return; - if(logging_fd < 0){ - flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); - logging_fd = os_open_file("log", flags, 0644); - } - gettimeofday(&tv, NULL); - sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, - tv.tv_usec); - va_start(ap, fmt); - vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); - va_end(ap); - write(logging_fd, logging_buf, strlen(logging_buf)); -} -#endif - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c deleted file mode 100644 index b1674bc..0000000 --- a/arch/um/kernel/tempfile.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include "init.h" - -/* Modified from create_mem_file and start_debugger */ -static char *tempdir = NULL; - -static void __init find_tempdir(void) -{ - char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; - int i; - char *dir = NULL; - - if(tempdir != NULL) return; /* We've already been called */ - for(i = 0; dirs[i]; i++){ - dir = getenv(dirs[i]); - if((dir != NULL) && (*dir != '\0')) - break; - } - if((dir == NULL) || (*dir == '\0')) - dir = "/tmp"; - - tempdir = malloc(strlen(dir) + 2); - if(tempdir == NULL){ - fprintf(stderr, "Failed to malloc tempdir, " - "errno = %d\n", errno); - return; - } - strcpy(tempdir, dir); - strcat(tempdir, "/"); -} - -int make_tempfile(const char *template, char **out_tempname, int do_unlink) -{ - char tempname[MAXPATHLEN]; - int fd; - - find_tempdir(); - if (*template != '/') - strcpy(tempname, tempdir); - else - *tempname = 0; - strcat(tempname, template); - fd = mkstemp(tempname); - if(fd < 0){ - fprintf(stderr, "open - cannot create %s: %s\n", tempname, - strerror(errno)); - return -1; - } - if(do_unlink && (unlink(tempname) < 0)){ - perror("unlink"); - return -1; - } - if(out_tempname){ - *out_tempname = strdup(tempname); - if(*out_tempname == NULL){ - perror("strdup"); - return -1; - } - } - return(fd); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 80ed618..0a562c3 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -307,7 +307,7 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) } else if(pte_newprot(*pte)){ updated = 1; - protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); + os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); } addr += PAGE_SIZE; } diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index 3085267..03e5898 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c @@ -12,6 +12,7 @@ #include "tt.h" #include "mem_user.h" #include "user_util.h" +#include "os.h" void remap_data(void *segment_start, void *segment_end, int w) { diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 09f6f7c..f0a2759 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -361,11 +361,6 @@ int linux_main(int argc, char **argv) uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, &host_task_size, &task_size); - /* Need to check this early because mmapping happens before the - * kernel is running. - */ - check_tmpexec(); - brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); /* Increase physical memory size for exec-shield users diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 7a16624..d15ec2a 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,11 +3,11 @@ # Licensed under the GPL # -obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ - tty.o user_syms.o drivers/ sys-$(SUBARCH)/ +obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ + tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/ -USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ - tty.o +USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ + time.o tt.o tty.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c new file mode 100644 index 0000000..8e71eda --- /dev/null +++ b/arch/um/os-Linux/mem.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kern_util.h" +#include "user.h" +#include "user_util.h" +#include "mem_user.h" +#include "init.h" +#include "os.h" +#include "tempfile.h" +#include "kern_constants.h" + +#include + +static char *tempdir = NULL; + +static void __init find_tempdir(void) +{ + char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; + int i; + char *dir = NULL; + + if(tempdir != NULL) return; /* We've already been called */ + for(i = 0; dirs[i]; i++){ + dir = getenv(dirs[i]); + if((dir != NULL) && (*dir != '\0')) + break; + } + if((dir == NULL) || (*dir == '\0')) + dir = "/tmp"; + + tempdir = malloc(strlen(dir) + 2); + if(tempdir == NULL){ + fprintf(stderr, "Failed to malloc tempdir, " + "errno = %d\n", errno); + return; + } + strcpy(tempdir, dir); + strcat(tempdir, "/"); +} + +/* + * This proc still used in tt-mode + * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). + * So it isn't 'static' yet. + */ +int make_tempfile(const char *template, char **out_tempname, int do_unlink) +{ + char tempname[MAXPATHLEN]; + int fd; + + find_tempdir(); + if (*template != '/') + strcpy(tempname, tempdir); + else + *tempname = 0; + strcat(tempname, template); + fd = mkstemp(tempname); + if(fd < 0){ + fprintf(stderr, "open - cannot create %s: %s\n", tempname, + strerror(errno)); + return -1; + } + if(do_unlink && (unlink(tempname) < 0)){ + perror("unlink"); + return -1; + } + if(out_tempname){ + *out_tempname = strdup(tempname); + if(*out_tempname == NULL){ + perror("strdup"); + return -1; + } + } + return(fd); +} + +#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" + +/* + * This proc is used in start_up.c + * So it isn't 'static'. + */ +int create_tmp_file(unsigned long len) +{ + int fd, err; + char zero; + + fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); + if(fd < 0) { + exit(1); + } + + err = fchmod(fd, 0777); + if(err < 0){ + perror("os_mode_fd"); + exit(1); + } + + if (lseek64(fd, len, SEEK_SET) < 0) { + perror("os_seek_file"); + exit(1); + } + + zero = 0; + + err = os_write_file(fd, &zero, 1); + if(err != 1){ + errno = -err; + perror("os_write_file"); + exit(1); + } + + return(fd); +} + +static int create_anon_file(unsigned long len) +{ + void *addr; + int fd; + + fd = open("/dev/anon", O_RDWR); + if(fd < 0) { + perror("opening /dev/anon"); + exit(1); + } + + addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if(addr == MAP_FAILED){ + perror("mapping physmem file"); + exit(1); + } + munmap(addr, len); + + return(fd); +} + +extern int have_devanon; + +int create_mem_file(unsigned long len) +{ + int err, fd; + + if(have_devanon) + fd = create_anon_file(len); + else fd = create_tmp_file(len); + + err = os_set_exec_close(fd, 1); + if(err < 0){ + errno = -err; + perror("exec_close"); + } + return(fd); +} diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 040cc14..6af8317 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -4,18 +4,22 @@ */ #include +#include +#include +#include +#include #include #include #include +#include #include -#include -#include #include #include #include #include #include #include +#include #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -25,6 +29,7 @@ #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" +#include "mem_user.h" #include "time_user.h" #include "init.h" #include "os.h" @@ -32,6 +37,8 @@ #include "choose-mode.h" #include "mode.h" #include "tempfile.h" +#include "kern_constants.h" + #ifdef UML_CONFIG_MODE_SKAS #include "skas.h" #include "skas_ptrace.h" @@ -276,9 +283,38 @@ static void __init check_ptrace(void) check_sysemu(); } +extern int create_tmp_file(unsigned long len); + +static void check_tmpexec(void) +{ + void *addr; + int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); + + addr = mmap(NULL, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); + printf("Checking PROT_EXEC mmap in /tmp..."); + fflush(stdout); + if(addr == MAP_FAILED){ + err = errno; + perror("failed"); + if(err == EPERM) + printf("/tmp must be not mounted noexec\n"); + exit(1); + } + printf("OK\n"); + munmap(addr, UM_KERN_PAGE_SIZE); + + close(fd); +} + void os_early_checks(void) { check_ptrace(); + + /* Need to check this early because mmapping happens before the + * kernel is running. + */ + check_tmpexec(); } static int __init noprocmm_cmd_param(char *str, int* add) @@ -357,3 +393,72 @@ int can_do_skas(void) return(0); } #endif + +int have_devanon = 0; + +void check_devanon(void) +{ + int fd; + + printk("Checking for /dev/anon on the host..."); + fd = open("/dev/anon", O_RDWR); + if(fd < 0){ + printk("Not available (open failed with errno %d)\n", errno); + return; + } + + printk("OK\n"); + have_devanon = 1; +} + +int __init parse_iomem(char *str, int *add) +{ + struct iomem_region *new; + struct uml_stat buf; + char *file, *driver; + int fd, err, size; + + driver = str; + file = strchr(str,','); + if(file == NULL){ + printf("parse_iomem : failed to parse iomem\n"); + goto out; + } + *file = '\0'; + file++; + fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); + if(fd < 0){ + os_print_error(fd, "parse_iomem - Couldn't open io file"); + goto out; + } + + err = os_stat_fd(fd, &buf); + if(err < 0){ + os_print_error(err, "parse_iomem - cannot stat_fd file"); + goto out_close; + } + + new = malloc(sizeof(*new)); + if(new == NULL){ + perror("Couldn't allocate iomem_region struct"); + goto out_close; + } + + size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); + + *new = ((struct iomem_region) { .next = iomem_regions, + .driver = driver, + .fd = fd, + .size = size, + .phys = 0, + .virt = 0 }); + iomem_regions = new; + iomem_size += new->size + UM_KERN_PAGE_SIZE; + + return(0); + out_close: + os_close_file(fd); + out: + return(1); +} + diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 5b047ab..a6db887 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c @@ -36,6 +36,20 @@ #include "mode.h" #include "tempfile.h" +int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, + int must_succeed) +{ + int err; + + err = os_protect_memory((void *) addr, len, r, w, x); + if(err < 0){ + if(must_succeed) + panic("protect failed, err = %d", -err); + else return(err); + } + return(0); +} + /* *------------------------- * only for tt mode (will be deleted in future...) -- cgit v0.10.2 From 114069f7384c15a7a9f8d3e333caf4d470dfe520 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:51 -0700 Subject: [PATCH] uml: merge mem_user.c and mem.c The serial UML OS-abstraction layer patch (um/kernel dir). This joins mem_user.c and mem.c files. Signed-off-by: Gennady Sharapov Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 7eb52c5..1a0001b 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -1,4 +1,4 @@ -# +# # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -7,11 +7,11 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec_kern.o exitcode.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ - physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ - sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \ - time.o time_kern.o tlb.o trap_kern.o trap_user.o \ - uaccess_user.o um_arch.o umid.o user_util.o + helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ + process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ + signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ + time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ + umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 64fa062..ea008b0 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -19,6 +19,10 @@ #include "mem_user.h" #include "uml_uaccess.h" #include "os.h" +#include "linux/types.h" +#include "linux/string.h" +#include "init.h" +#include "kern_constants.h" extern char __binary_start; @@ -368,6 +372,16 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) return pte; } +struct iomem_region *iomem_regions = NULL; +int iomem_size = 0; + +extern int parse_iomem(char *str, int *add) __init; + +__uml_setup("iomem=", parse_iomem, +"iomem=,\n" +" Configure as an IO memory region named .\n\n" +); + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c deleted file mode 100644 index d49640d..0000000 --- a/arch/um/kernel/mem_user.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * arch/um/kernel/mem_user.c - * - * BRIEF MODULE DESCRIPTION - * user side memory routines for supporting IO memory inside user mode linux - * - * Copyright (C) 2001 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com - * - * 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. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' 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 THE AUTHOR 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kern_util.h" -#include "user.h" -#include "user_util.h" -#include "mem_user.h" -#include "init.h" -#include "os.h" -#include "tempfile.h" -#include "kern_constants.h" - -struct iomem_region *iomem_regions = NULL; -int iomem_size = 0; - -extern int parse_iomem(char *str, int *add) __init; - -__uml_setup("iomem=", parse_iomem, -"iomem=,\n" -" Configure as an IO memory region named .\n\n" -); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v0.10.2 From 2867ace6751adc20bb37cfb09478510c49110b27 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:51 -0700 Subject: [PATCH] uml: return a real error code do_aio used to return -1 on error instead of errno. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index e942beb..298d563 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -117,6 +117,8 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio) err = io_submit(ctx, 1, &iocbp); if(err > 0) err = 0; + else + err = -errno; out: return err; -- cgit v0.10.2 From 1f87b1e6e6050c0afe8b4afc279121f99043dc54 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:27:52 -0700 Subject: [PATCH] uml: remove include of asm/elf.h asm/elf.h is bad on x86_64, and i386 doesn't need it any more after Al's cleanup. Signed-off-by: Jeff Dike Cc: Paolo Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 5c02e33..e770cb0 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -9,7 +9,6 @@ */ #include #include -#include #include "init.h" #include "elf_user.h" #include "mem_user.h" -- cgit v0.10.2 From e36d394deb1b59d004ab057e0b5c505ffc5d8c0a Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 16 Sep 2005 19:27:53 -0700 Subject: [PATCH] Fix up some pm_message_t types Fix up some pm_message_t types Signed-Off-By: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 2786f7c..a7bd857 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -551,7 +551,7 @@ struct locomo_save_data { u16 LCM_SPIMD; }; -static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) +static int locomo_suspend(struct device *dev, pm_message_t state, u32 level) { struct locomo *lchip = dev_get_drvdata(dev); struct locomo_save_data *save; diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 2e0ea92..9a7e874 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -575,7 +575,7 @@ static void openpic2_cached_disable_irq(u_int irq) * we need something better to deal with that... Maybe switch to S1 for * cpufreq changes */ -int openpic2_suspend(struct sys_device *sysdev, u32 state) +int openpic2_suspend(struct sys_device *sysdev, pm_message_t state) { int i; unsigned long flags; diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a3cd0ee..0585ab2 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev) #ifdef CONFIG_PM static int -mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level) +mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index cabd53c..6c2244c 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int imxfb_suspend(struct device *dev, u32 state, u32 level) +static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level) { struct imxfb_info *fbi = dev_get_drvdata(dev); pr_debug("%s\n",__FUNCTION__); diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 34195b74..b2d5db2 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -650,7 +650,7 @@ static int aaci_do_resume(snd_card_t *card, unsigned int state) return 0; } -static int aaci_suspend(struct amba_device *dev, u32 state) +static int aaci_suspend(struct amba_device *dev, pm_message_t state) { snd_card_t *card = amba_get_drvdata(dev); return card ? aaci_do_suspend(card) : 0; -- cgit v0.10.2 From b9491ac835829e6a34e2bbaa8adad261c71bf990 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 16 Sep 2005 19:27:54 -0700 Subject: [PATCH] x86_64: e820.c needs module.h For EXPORT_SYMBOL. Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 4e34b0f..ab3f87a 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -17,6 +17,8 @@ #include #include #include +#include + #include #include #include -- cgit v0.10.2 From f3519f91942f2b43942400348c16d63fe9327f04 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Fri, 16 Sep 2005 19:27:54 -0700 Subject: [PATCH] fix mm/Kconfig spelling Signed-off-by: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/Kconfig b/mm/Kconfig index 4e9937a..391ffc5 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -29,7 +29,7 @@ config FLATMEM_MANUAL If unsure, choose this option (Flat Memory) over any other. config DISCONTIGMEM_MANUAL - bool "Discontigious Memory" + bool "Discontiguous Memory" depends on ARCH_DISCONTIGMEM_ENABLE help This option provides enhanced support for discontiguous @@ -52,7 +52,7 @@ config SPARSEMEM_MANUAL memory hotplug systems. This is normal. For many other systems, this will be an alternative to - "Discontigious Memory". This option provides some potential + "Discontiguous Memory". This option provides some potential performance benefits, along with decreased code complexity, but it is newer, and more experimental. -- cgit v0.10.2 From 73a0b538ee573a76cba59cdc9f177a71776d4678 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 16 Sep 2005 19:27:55 -0700 Subject: [PATCH] x86_64: desc.h-needs smp.h include/asm/desc.h: In function `load_LDT': include/asm/desc.h:209: warning: implicit declaration of function `get_cpu' include/asm/desc.h:211: warning: implicit declaration of function `put_cpu' Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 594e610..68ac3c6 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h @@ -8,6 +8,8 @@ #ifndef __ASSEMBLY__ #include +#include + #include #include -- cgit v0.10.2 From d15c5749eb81dee94d40fe12584ca8461858b4cb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 16 Sep 2005 19:27:56 -0700 Subject: [PATCH] seclvl-use-securityfs tidy We don't put braces around single statements, thanks. Cc: Serge Hallyn Cc: James Morris Cc: Chris Wright Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/security/seclvl.c b/security/seclvl.c index dc4e17b..241093d 100644 --- a/security/seclvl.c +++ b/security/seclvl.c @@ -253,9 +253,8 @@ passwd_write_file(struct file * file, const char __user * buf, if (count < 0 || count >= PAGE_SIZE) return -ENOMEM; - if (*ppos != 0) { + if (*ppos != 0) return -EINVAL; - } page = (char *)get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; @@ -265,9 +264,8 @@ passwd_write_file(struct file * file, const char __user * buf, len = strlen(page); /* ``echo "secret" > seclvl/passwd'' includes a newline */ - if (page[len - 1] == '\n') { + if (page[len - 1] == '\n') len--; - } /* Hash the password, then compare the hashed values */ if ((rc = plaintext_to_sha1(tmp, page, len))) { seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " @@ -275,9 +273,8 @@ passwd_write_file(struct file * file, const char __user * buf, return rc; } for (i = 0; i < SHA1_DIGEST_SIZE; i++) { - if (hashedPassword[i] != tmp[i]) { + if (hashedPassword[i] != tmp[i]) return -EPERM; - } } seclvl_printk(0, KERN_INFO, "Password accepted; seclvl reduced to 0.\n"); @@ -482,9 +479,8 @@ static void seclvl_file_free_security(struct file *filp) */ static int seclvl_umount(struct vfsmount *mnt, int flags) { - if (current->pid == 1) { + if (current->pid == 1) return 0; - } if (seclvl == 2) { seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " "level %d\n", seclvl); @@ -638,9 +634,8 @@ static int __init seclvl_init(void) static void __exit seclvl_exit(void) { securityfs_remove(seclvl_ino); - if (*passwd || *sha1_passwd) { + if (*passwd || *sha1_passwd) securityfs_remove(passwd_ino); - } securityfs_remove(dir_ino); if (secondary == 1) { mod_unreg_security(MY_NAME, &seclvl_ops); -- cgit v0.10.2 From 9afa57b04ca08ff061e54787e3becf5c40283149 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Fri, 16 Sep 2005 19:27:57 -0700 Subject: [PATCH] seclvl: use securityfs (fix) That should be -EINVAL for both. Signed-off-by: Serge Hallyn Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/security/seclvl.c b/security/seclvl.c index 241093d..1caac01 100644 --- a/security/seclvl.c +++ b/security/seclvl.c @@ -252,7 +252,7 @@ passwd_write_file(struct file * file, const char __user * buf, } if (count < 0 || count >= PAGE_SIZE) - return -ENOMEM; + return -EINVAL; if (*ppos != 0) return -EINVAL; page = (char *)get_zeroed_page(GFP_KERNEL); -- cgit v0.10.2 From 8a70ce8a4b1c9d39e0a180173728a8d102274631 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 16 Sep 2005 19:27:58 -0700 Subject: [PATCH] ppc64: build fix I forgot to include siginfo.h when I added data breakpoint support. We must include it in a round-a-bout way in mainline. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 7fbc68b..be3f25c 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c @@ -38,6 +38,7 @@ #include #include #include +#include /* * Check whether the instruction at regs->nip is a store using -- cgit v0.10.2 From 0faf3d3d08bb20d803ba090a1bc1ffedaea6ced6 Mon Sep 17 00:00:00 2001 From: Thomas Maguin Date: Fri, 16 Sep 2005 19:27:58 -0700 Subject: [PATCH] scsi_ioctl: Add WRITE_LONG_2 as write safe command Add WRITE_LONG_2 as write safe commands, which which allows normal users to make a c1-, c2- and cu-scan (so called cxscan) with readcd on cxscan-capable cd/dvd-writers Signed-off-by: Jens Axboe Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 856c227..079ec34 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -168,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd) safe_for_write(WRITE_VERIFY_12), safe_for_write(WRITE_16), safe_for_write(WRITE_LONG), + safe_for_write(WRITE_LONG_2), safe_for_write(ERASE), safe_for_write(GPCMD_MODE_SELECT_10), safe_for_write(MODE_SELECT), -- cgit v0.10.2 From 514ccd4e6c414d8064d53235f7fc09fc02ec2078 Mon Sep 17 00:00:00 2001 From: Vitaly Bordug Date: Fri, 16 Sep 2005 19:28:00 -0700 Subject: [PATCH] ppc32: Add ppc_sys descriptions for PowerQUICC I devices Added ppc_sys device and system definitions for PowerQUICC I devices. This will allow drivers for PQI to be proper platform device drivers. Currently sys section contains only MPC885 and MPC866. Identification should be done with identify_ppc_sys_by_name call, with board-specific "name" string passed, since PQI do not have any register that could identify the SOC. Signed-off-by: Vitaly Bordug Signed-off-by: Kumar Gala Signed-off-by: Marcelo Tosatti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 8b9b226..b8d08f3 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -34,7 +34,8 @@ ifeq ($(CONFIG_40x),y) obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o endif endif -obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) +obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ + ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o ifeq ($(CONFIG_8xx),y) obj-$(CONFIG_PCI) += qspan_pci.o i8259.o endif diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c new file mode 100644 index 0000000..2b5f0e7 --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_devices.c @@ -0,0 +1,224 @@ +/* + * arch/ppc/syslib/mpc8xx_devices.c + * + * MPC8xx Device descriptions + * + * Maintainer: Kumar Gala + * + * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* We use offsets for IORESOURCE_MEM to do not set dependences at compile time. + * They will get fixed up by mach_mpc8xx_fixup + */ + +struct platform_device ppc_sys_platform_devices[] = { + [MPC8xx_CPM_FEC1] = { + .name = "fsl-cpm-fec", + .id = 1, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xe00, + .end = 0xe88, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_FEC1, + .end = MPC8xx_INT_FEC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_FEC2] = { + .name = "fsl-cpm-fec", + .id = 2, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0x1e00, + .end = 0x1e88, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_FEC2, + .end = MPC8xx_INT_FEC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC1] = { + .name = "fsl-cpm-scc", + .id = 1, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa00, + .end = 0xa18, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3c00, + .end = 0x3c80, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SCC1, + .end = MPC8xx_INT_SCC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC2] = { + .name = "fsl-cpm-scc", + .id = 2, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa20, + .end = 0xa38, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3d00, + .end = 0x3d80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC2, + .end = MPC8xx_INT_SCC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC3] = { + .name = "fsl-cpm-scc", + .id = 3, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa40, + .end = 0xa58, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3e00, + .end = 0x3e80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC3, + .end = MPC8xx_INT_SCC3, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SCC4] = { + .name = "fsl-cpm-scc", + .id = 4, + .num_resources = 3, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa60, + .end = 0xa78, + .flags = IORESOURCE_MEM, + }, + { + .name = "pram", + .start = 0x3f00, + .end = 0x3f80, + .flags = IORESOURCE_MEM, + }, + + { + .name = "interrupt", + .start = MPC8xx_INT_SCC4, + .end = MPC8xx_INT_SCC4, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SMC1] = { + .name = "fsl-cpm-smc", + .id = 1, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa82, + .end = 0xa91, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SMC1, + .end = MPC8xx_INT_SMC1, + .flags = IORESOURCE_IRQ, + }, + }, + }, + [MPC8xx_CPM_SMC2] = { + .name = "fsl-cpm-smc", + .id = 2, + .num_resources = 2, + .resource = (struct resource[]) { + { + .name = "regs", + .start = 0xa92, + .end = 0xaa1, + .flags = IORESOURCE_MEM, + }, + { + .name = "interrupt", + .start = MPC8xx_INT_SMC2, + .end = MPC8xx_INT_SMC2, + .flags = IORESOURCE_IRQ, + }, + }, + }, +}; + +static int __init mach_mpc8xx_fixup(struct platform_device *pdev) +{ + ppc_sys_fixup_mem_resource (pdev, IMAP_ADDR); + return 0; +} + +static int __init mach_mpc8xx_init(void) +{ + ppc_sys_device_fixup = mach_mpc8xx_fixup; + return 0; +} + +postcore_initcall(mach_mpc8xx_init); diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c new file mode 100644 index 0000000..a532ccc --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_sys.c @@ -0,0 +1,61 @@ +/* + * arch/ppc/platforms/mpc8xx_sys.c + * + * MPC8xx System descriptions + * + * Maintainer: Kumar Gala + * + * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug + * + * 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. + */ + +#include +#include +#include +#include + +struct ppc_sys_spec *cur_ppc_sys_spec; +struct ppc_sys_spec ppc_sys_specs[] = { + { + .ppc_sys_name = "MPC86X", + .mask = 0xFFFFFFFF, + .value = 0x00000000, + .num_devices = 2, + .device_list = (enum ppc_sys_devices[]) + { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + }, + }, + { + .ppc_sys_name = "MPC885", + .mask = 0xFFFFFFFF, + .value = 0x00000000, + .num_devices = 3, + .device_list = (enum ppc_sys_devices[]) + { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_FEC2, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + }, + }, + { /* default match */ + .ppc_sys_name = "", + .mask = 0x00000000, + .value = 0x00000000, + }, +}; diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h index 5575247..bd96748 100644 --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h @@ -138,6 +138,16 @@ irq_canonicalize(int irq) #define SIU_IRQ7 (14) #define SIU_LEVEL7 (15) +#define MPC8xx_INT_FEC1 SIU_LEVEL1 +#define MPC8xx_INT_FEC2 SIU_LEVEL3 + +#define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1) +#define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2) +#define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3) +#define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4) +#define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1) +#define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2) + /* The internal interrupts we can configure as we see fit. * My personal preference is CPM at level 2, which puts it above the * MBX PCI/ISA/IDE interrupts. diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h index dc8e598..208a2e1 100644 --- a/include/asm-ppc/mpc8xx.h +++ b/include/asm-ppc/mpc8xx.h @@ -97,6 +97,22 @@ extern unsigned char __res[]; struct pt_regs; +enum ppc_sys_devices { + MPC8xx_CPM_FEC1, + MPC8xx_CPM_FEC2, + MPC8xx_CPM_I2C, + MPC8xx_CPM_SCC1, + MPC8xx_CPM_SCC2, + MPC8xx_CPM_SCC3, + MPC8xx_CPM_SCC4, + MPC8xx_CPM_SPI, + MPC8xx_CPM_MCC1, + MPC8xx_CPM_MCC2, + MPC8xx_CPM_SMC1, + MPC8xx_CPM_SMC2, + MPC8xx_CPM_USB, +}; + #endif /* !__ASSEMBLY__ */ #endif /* CONFIG_8xx */ #endif /* __CONFIG_8xx_DEFS */ diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 048f7c8..549f448 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -27,6 +27,8 @@ #include #elif defined(CONFIG_85xx) #include +#elif defined(CONFIG_8xx) +#include #elif defined(CONFIG_PPC_MPC52xx) #include #elif defined(CONFIG_MPC10X_BRIDGE) -- cgit v0.10.2 From afeda2c24e74cbddde376e06fdd82c215f9cb637 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 16 Sep 2005 19:28:01 -0700 Subject: [PATCH] relayfs documentation typo Small typo in relayfs documentation. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt index d24e1b0..d803abe 100644 --- a/Documentation/filesystems/relayfs.txt +++ b/Documentation/filesystems/relayfs.txt @@ -15,7 +15,7 @@ retrieve the data as it becomes available. The format of the data logged into the channel buffers is completely up to the relayfs client; relayfs does however provide hooks which -allow clients to impose some stucture on the buffer data. Nor does +allow clients to impose some structure on the buffer data. Nor does relayfs implement any form of data filtering - this also is left to the client. The purpose is to keep relayfs as simple as possible. -- cgit v0.10.2 From 2030c0fd3db3332378f95f479c286181e3920644 Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Fri, 16 Sep 2005 19:28:02 -0700 Subject: [PATCH] PR_GET_DUMPABLE returns incorrect info 2.6.13 incorporated Alan Cox's patch for /proc/sys/fs/suid_dumpable (one version of this patch can be found here http://marc.theaimsgroup.com/?l=linux-kernel&m=109647550421014&w=2 ). This patch also made corresponding changes in kernel/sys.c to change the prctl() PR_SET_DUMPABLE operation so that the permitted range of 'arg2' was modified from 0..1 to 0..2. However, a corresponding change was not made for PR_GET_DUMPABLE: if the dumpable flag is non-zero, then PR_GET_DUMPABLE always returns 1, so that the caller can't determine the true setting of this flag. Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/sys.c b/kernel/sys.c index c80412b..f723522 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, error = put_user(current->pdeath_signal, (int __user *)arg2); break; case PR_GET_DUMPABLE: - if (current->mm->dumpable) - error = 1; + error = current->mm->dumpable; break; case PR_SET_DUMPABLE: if (arg2 < 0 || arg2 > 2) { -- cgit v0.10.2 From 3013449243adc3421b507696e5d247a3d292ee0c Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Fri, 16 Sep 2005 19:28:03 -0700 Subject: [PATCH] uml: UML/i386 cmpxchg fix Using native cmpxchg offers a slight performance improvement in uml/i386. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 8ad156a..5d92cac 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -42,3 +42,7 @@ config ARCH_HAS_SC_SIGNALS config ARCH_REUSE_HOST_VSYSCALL_AREA bool default y + +config X86_CMPXCHG + bool + default y diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h index ea8381d..c436263 100644 --- a/include/asm-um/system-i386.h +++ b/include/asm-um/system-i386.h @@ -3,6 +3,4 @@ #include "asm/system-generic.h" -#define __HAVE_ARCH_CMPXCHG 1 - #endif -- cgit v0.10.2 From e61c0e336f3931842f09e6709d76146bfd81184e Mon Sep 17 00:00:00 2001 From: Abhay Salunke Date: Fri, 16 Sep 2005 19:28:04 -0700 Subject: [PATCH] dell_rbu: enhancements and fixes BUG fixes: The driver used to allocate memory with spinlock held which has been fixed in this patch. The driver was printing the entire buffer when it received a invalid entry in image_type. The fix is to only print a warning message and not the buffer. Usability enhancements: It is possible that due to user error the /sys/class/firmware/dell_rbu entries might be missing, this can happen if the user does the following echo 1 > /sys/class/firmware/dell_rbu/loading echo 0 > /sys/class/firmware/dell_rbu/loading This will make the entries in /sys/class/firmware/ to disappear and the only way get them back was bby unloading and loading the driver. This patch makes the user recreate these entries by echoing init in to image_type. This patch has been tested with Libsmbios and Dell OpenManage. Signed-off-by: Abhay Salunke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index bcfa5c3..95d7f62 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt @@ -13,6 +13,8 @@ the BIOS on Dell servers (starting from servers sold since 1999), desktops and notebooks (starting from those sold in 2005). Please go to http://support.dell.com register and you can find info on OpenManage and Dell Update packages (DUP). +Libsmbios can also be used to update BIOS on Dell systems go to +http://linux.dell.com/libsmbios/ for details. Dell_RBU driver supports BIOS update using the monilothic image and packetized image methods. In case of moniolithic the driver allocates a contiguous chunk @@ -22,8 +24,8 @@ would place each packet in contiguous physical memory. The driver also maintains a link list of packets for reading them back. If the dell_rbu driver is unloaded all the allocated memory is freed. -The rbu driver needs to have an application which will inform the BIOS to -enable the update in the next system reboot. +The rbu driver needs to have an application (as mentioned above)which will +inform the BIOS to enable the update in the next system reboot. The user should not unload the rbu driver after downloading the BIOS image or updating. @@ -42,9 +44,11 @@ In case of packet mechanism the single memory can be broken in smaller chuks of contiguous memory and the BIOS image is scattered in these packets. By default the driver uses monolithic memory for the update type. This can be -changed to contiguous during the driver load time by specifying the load +changed to packets during the driver load time by specifying the load parameter image_type=packet. This can also be changed later as below echo packet > /sys/devices/platform/dell_rbu/image_type +Also echoing either mono ,packet or init in to image_type will free up the +memory allocated by the driver. Do the steps below to download the BIOS image. 1) echo 1 > /sys/class/firmware/dell_rbu/loading @@ -53,9 +57,13 @@ Do the steps below to download the BIOS image. The /sys/class/firmware/dell_rbu/ entries will remain till the following is done. -echo -1 > /sys/class/firmware/dell_rbu/loading - +echo -1 > /sys/class/firmware/dell_rbu/loading. Until this step is completed the drivr cannot be unloaded. +If an user by accident executes steps 1 and 3 above without executing step 2; +it will make the /sys/class/firmware/dell_rbu/ entries to disappear. +The entries can be recreated by doing the following +echo init > /sys/devices/platform/dell_rbu/image_type +NOTE: echoing init in image_type does not change it original value. Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to read back the image downloaded. This is useful in case of packet update diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3b865f3..9c2c2b1 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -50,7 +50,7 @@ MODULE_AUTHOR("Abhay Salunke "); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0"); +MODULE_VERSION("2.0"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -65,10 +65,11 @@ static struct _rbu_data { unsigned long packet_write_count; unsigned long num_packets; unsigned long packetsize; + int entry_created; } rbu_data; -static char image_type[MAX_IMAGE_LENGTH] = "mono"; -module_param_string(image_type, image_type, sizeof(image_type), 0); +static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; +module_param_string(image_type, image_type, sizeof (image_type), 0); MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); struct packet_data { @@ -84,7 +85,8 @@ static struct platform_device *rbu_device; static int context; static dma_addr_t dell_rbu_dmaaddr; -static void init_packet_head(void) +static void +init_packet_head(void) { INIT_LIST_HEAD(&packet_data_head.list); rbu_data.packet_write_count = 0; @@ -93,7 +95,8 @@ static void init_packet_head(void) rbu_data.packetsize = 0; } -static int fill_last_packet(void *data, size_t length) +static int +fill_last_packet(void *data, size_t length) { struct list_head *ptemp_list; struct packet_data *packet = NULL; @@ -114,7 +117,7 @@ static int fill_last_packet(void *data, size_t length) if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { pr_debug("dell_rbu:%s: packet size data " - "overrun\n", __FUNCTION__); + "overrun\n", __FUNCTION__); return -EINVAL; } @@ -135,7 +138,8 @@ static int fill_last_packet(void *data, size_t length) return 0; } -static int create_packet(size_t length) +static int +create_packet(size_t length) { struct packet_data *newpacket; int ordernum = 0; @@ -146,12 +150,14 @@ static int create_packet(size_t length) pr_debug("create_packet: packetsize not specified\n"); return -EINVAL; } + spin_unlock(&rbu_data.lock); + newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); + spin_lock(&rbu_data.lock); - newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); if (!newpacket) { printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __FUNCTION__); + "dell_rbu:%s: failed to allocate new " + "packet\n", __FUNCTION__); return -ENOMEM; } @@ -160,15 +166,17 @@ static int create_packet(size_t length) * there is no upper limit on memory * address for packetized mechanism */ - newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, - ordernum); + spin_unlock(&rbu_data.lock); + newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, + ordernum); + spin_lock(&rbu_data.lock); pr_debug("create_packet: newpacket %p\n", newpacket->data); if (!newpacket->data) { printk(KERN_WARNING - "dell_rbu:%s: failed to allocate new " - "packet\n", __FUNCTION__); + "dell_rbu:%s: failed to allocate new " + "packet\n", __FUNCTION__); kfree(newpacket); return -ENOMEM; } @@ -190,7 +198,8 @@ static int create_packet(size_t length) return 0; } -static int packetize_data(void *data, size_t length) +static int +packetize_data(void *data, size_t length) { int rc = 0; @@ -206,7 +215,7 @@ static int packetize_data(void *data, size_t length) static int do_packet_read(char *data, struct list_head *ptemp_list, - int length, int bytes_read, int *list_read_count) + int length, int bytes_read, int *list_read_count) { void *ptemp_buf; struct packet_data *newpacket = NULL; @@ -239,7 +248,8 @@ do_packet_read(char *data, struct list_head *ptemp_list, return bytes_copied; } -static int packet_read_list(char *data, size_t * pread_length) +static int +packet_read_list(char *data, size_t * pread_length) { struct list_head *ptemp_list; int temp_count = 0; @@ -258,8 +268,7 @@ static int packet_read_list(char *data, size_t * pread_length) ptemp_list = (&packet_data_head.list)->next; while (!list_empty(ptemp_list)) { bytes_copied = do_packet_read(pdest, ptemp_list, - remaining_bytes, bytes_read, - &temp_count); + remaining_bytes, bytes_read, &temp_count); remaining_bytes -= bytes_copied; bytes_read += bytes_copied; pdest += bytes_copied; @@ -278,7 +287,8 @@ static int packet_read_list(char *data, size_t * pread_length) return 0; } -static void packet_empty_list(void) +static void +packet_empty_list(void) { struct list_head *ptemp_list; struct list_head *pnext_list; @@ -287,7 +297,7 @@ static void packet_empty_list(void) ptemp_list = (&packet_data_head.list)->next; while (!list_empty(ptemp_list)) { newpacket = - list_entry(ptemp_list, struct packet_data, list); + list_entry(ptemp_list, struct packet_data, list); pnext_list = ptemp_list->next; list_del(ptemp_list); ptemp_list = pnext_list; @@ -296,8 +306,8 @@ static void packet_empty_list(void) * to make sure there are no stale RBU packets left in memory */ memset(newpacket->data, 0, rbu_data.packetsize); - free_pages((unsigned long)newpacket->data, - newpacket->ordernum); + free_pages((unsigned long) newpacket->data, + newpacket->ordernum); kfree(newpacket); } rbu_data.packet_write_count = 0; @@ -310,7 +320,8 @@ static void packet_empty_list(void) * img_update_free: Frees the buffer allocated for storing BIOS image * Always called with lock held and returned with lock held */ -static void img_update_free(void) +static void +img_update_free(void) { if (!rbu_data.image_update_buffer) return; @@ -319,14 +330,13 @@ static void img_update_free(void) * BIOS image copied in memory. */ memset(rbu_data.image_update_buffer, 0, - rbu_data.image_update_buffer_size); + rbu_data.image_update_buffer_size); if (rbu_data.dma_alloc == 1) dma_free_coherent(NULL, rbu_data.bios_image_size, - rbu_data.image_update_buffer, - dell_rbu_dmaaddr); + rbu_data.image_update_buffer, dell_rbu_dmaaddr); else - free_pages((unsigned long)rbu_data.image_update_buffer, - rbu_data.image_update_ordernum); + free_pages((unsigned long) rbu_data.image_update_buffer, + rbu_data.image_update_ordernum); /* * Re-initialize the rbu_data variables after a free @@ -348,7 +358,8 @@ static void img_update_free(void) * already allocated size, then that memory is reused. This function is * called with lock held and returns with lock held. */ -static int img_update_realloc(unsigned long size) +static int +img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; unsigned long rc; @@ -366,7 +377,7 @@ static int img_update_realloc(unsigned long size) */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { printk(KERN_ERR "dell_rbu:%s: corruption " - "check failed\n", __FUNCTION__); + "check failed\n", __FUNCTION__); return -EINVAL; } /* @@ -385,17 +396,16 @@ static int img_update_realloc(unsigned long size) ordernum = get_order(size); image_update_buffer = - (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); + (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); img_buf_phys_addr = - (unsigned long)virt_to_phys(image_update_buffer); + (unsigned long) virt_to_phys(image_update_buffer); if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { - free_pages((unsigned long)image_update_buffer, ordernum); + free_pages((unsigned long) image_update_buffer, ordernum); ordernum = -1; image_update_buffer = dma_alloc_coherent(NULL, size, - &dell_rbu_dmaaddr, - GFP_KERNEL); + &dell_rbu_dmaaddr, GFP_KERNEL); dma_alloc = 1; } @@ -405,20 +415,21 @@ static int img_update_realloc(unsigned long size) rbu_data.image_update_buffer = image_update_buffer; rbu_data.image_update_buffer_size = size; rbu_data.bios_image_size = - rbu_data.image_update_buffer_size; + rbu_data.image_update_buffer_size; rbu_data.image_update_ordernum = ordernum; rbu_data.dma_alloc = dma_alloc; rc = 0; } else { pr_debug("Not enough memory for image update:" - "size = %ld\n", size); + "size = %ld\n", size); rc = -ENOMEM; } return rc; } -static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) +static ssize_t +read_packet_data(char *buffer, loff_t pos, size_t count) { int retval; size_t bytes_left; @@ -438,7 +449,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) if (pos > imagesize) { retval = 0; printk(KERN_WARNING "dell_rbu:read_packet_data: " - "data underrun\n"); + "data underrun\n"); goto read_rbu_data_exit; } @@ -459,7 +470,8 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) return retval; } -static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) +static ssize_t +read_rbu_mono_data(char *buffer, loff_t pos, size_t count) { unsigned char *ptemp = NULL; size_t bytes_left = 0; @@ -468,11 +480,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) /* check to see if we have something to return */ if ((rbu_data.image_update_buffer == NULL) || - (rbu_data.bios_image_size == 0)) { + (rbu_data.bios_image_size == 0)) { pr_debug("read_rbu_data_mono: image_update_buffer %p ," - "bios_image_size %lu\n", - rbu_data.image_update_buffer, - rbu_data.bios_image_size); + "bios_image_size %lu\n", + rbu_data.image_update_buffer, + rbu_data.bios_image_size); ret_count = -ENOMEM; goto read_rbu_data_exit; } @@ -515,9 +527,46 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) return ret_count; } +static void +callbackfn_rbu(const struct firmware *fw, void *context) +{ + int rc = 0; + + if (!fw || !fw->size) { + rbu_data.entry_created = 0; + return; + } + + spin_lock(&rbu_data.lock); + if (!strcmp(image_type, "mono")) { + if (!img_update_realloc(fw->size)) + memcpy(rbu_data.image_update_buffer, + fw->data, fw->size); + } else if (!strcmp(image_type, "packet")) { + if (!rbu_data.packetsize) + rbu_data.packetsize = fw->size; + else if (rbu_data.packetsize != fw->size) { + packet_empty_list(); + rbu_data.packetsize = fw->size; + } + packetize_data(fw->data, fw->size); + } else + pr_debug("invalid image type specified.\n"); + spin_unlock(&rbu_data.lock); + + rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); + if (rc) + printk(KERN_ERR + "dell_rbu:%s request_firmware_nowait failed" + " %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; +} + static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) + size_t count) { int size = 0; if (!pos) @@ -527,25 +576,63 @@ read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) + size_t count) { int rc = count; + int req_firm_rc = 0; + int i; spin_lock(&rbu_data.lock); - - if (strlen(buffer) < MAX_IMAGE_LENGTH) - sscanf(buffer, "%s", image_type); - else - printk(KERN_WARNING "dell_rbu: image_type is invalid" - "max chars = %d, \n incoming str--%s-- \n", - MAX_IMAGE_LENGTH, buffer); + /* + * Find the first newline or space + */ + for (i = 0; i < count; ++i) + if (buffer[i] == '\n' || buffer[i] == ' ') { + buffer[i] = '\0'; + break; + } + if (i == count) + buffer[count] = '\0'; + + if (strstr(buffer, "mono")) + strcpy(image_type, "mono"); + else if (strstr(buffer, "packet")) + strcpy(image_type, "packet"); + else if (strstr(buffer, "init")) { + /* + * If due to the user error the driver gets in a bad + * state where even though it is loaded , the + * /sys/class/firmware/dell_rbu entries are missing. + * to cover this situation the user can recreate entries + * by writing init to image_type. + */ + if (!rbu_data.entry_created) { + spin_unlock(&rbu_data.lock); + req_firm_rc = request_firmware_nowait(THIS_MODULE, + FW_ACTION_NOHOTPLUG, "dell_rbu", + &rbu_device->dev, &context, + callbackfn_rbu); + if (req_firm_rc) { + printk(KERN_ERR + "dell_rbu:%s request_firmware_nowait" + " failed %d\n", __FUNCTION__, rc); + rc = -EIO; + } else + rbu_data.entry_created = 1; + + spin_lock(&rbu_data.lock); + } + } else { + printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); + spin_unlock(&rbu_data.lock); + return -EINVAL; + } /* we must free all previous allocations */ packet_empty_list(); img_update_free(); - spin_unlock(&rbu_data.lock); - return rc; + return rc; } static struct bin_attribute rbu_data_attr = { @@ -559,51 +646,19 @@ static struct bin_attribute rbu_image_type_attr = { .write = write_rbu_image_type, }; -static void callbackfn_rbu(const struct firmware *fw, void *context) -{ - int rc = 0; - - if (!fw || !fw->size) - return; - - spin_lock(&rbu_data.lock); - if (!strcmp(image_type, "mono")) { - if (!img_update_realloc(fw->size)) - memcpy(rbu_data.image_update_buffer, - fw->data, fw->size); - } else if (!strcmp(image_type, "packet")) { - if (!rbu_data.packetsize) - rbu_data.packetsize = fw->size; - else if (rbu_data.packetsize != fw->size) { - packet_empty_list(); - rbu_data.packetsize = fw->size; - } - packetize_data(fw->data, fw->size); - } else - pr_debug("invalid image type specified.\n"); - spin_unlock(&rbu_data.lock); - - rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, - &context, callbackfn_rbu); - if (rc) - printk(KERN_ERR - "dell_rbu:%s request_firmware_nowait failed" - " %d\n", __FUNCTION__, rc); -} - -static int __init dcdrbu_init(void) +static int __init +dcdrbu_init(void) { int rc = 0; spin_lock_init(&rbu_data.lock); init_packet_head(); rbu_device = - platform_device_register_simple("dell_rbu", -1, NULL, 0); + platform_device_register_simple("dell_rbu", -1, NULL, 0); if (!rbu_device) { printk(KERN_ERR - "dell_rbu:%s:platform_device_register_simple " - "failed\n", __FUNCTION__); + "dell_rbu:%s:platform_device_register_simple " + "failed\n", __FUNCTION__); return -EIO; } @@ -611,17 +666,19 @@ static int __init dcdrbu_init(void) sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, - "dell_rbu", &rbu_device->dev, - &context, callbackfn_rbu); + "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); if (rc) printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" - " failed %d\n", __FUNCTION__, rc); + " failed %d\n", __FUNCTION__, rc); + else + rbu_data.entry_created = 1; return rc; } -static __exit void dcdrbu_exit(void) +static __exit void +dcdrbu_exit(void) { spin_lock(&rbu_data.lock); packet_empty_list(); -- cgit v0.10.2 From dda8577fb5a00507e5aea737833190a10516b257 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 16 Sep 2005 19:28:05 -0700 Subject: [PATCH] dell_rbu tidy Whitespace standardisation. Cc: Abhay Salunke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 9c2c2b1..b667823 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -85,8 +85,7 @@ static struct platform_device *rbu_device; static int context; static dma_addr_t dell_rbu_dmaaddr; -static void -init_packet_head(void) +static void init_packet_head(void) { INIT_LIST_HEAD(&packet_data_head.list); rbu_data.packet_write_count = 0; @@ -95,8 +94,7 @@ init_packet_head(void) rbu_data.packetsize = 0; } -static int -fill_last_packet(void *data, size_t length) +static int fill_last_packet(void *data, size_t length) { struct list_head *ptemp_list; struct packet_data *packet = NULL; @@ -138,8 +136,7 @@ fill_last_packet(void *data, size_t length) return 0; } -static int -create_packet(size_t length) +static int create_packet(size_t length) { struct packet_data *newpacket; int ordernum = 0; @@ -198,8 +195,7 @@ create_packet(size_t length) return 0; } -static int -packetize_data(void *data, size_t length) +static int packetize_data(void *data, size_t length) { int rc = 0; @@ -213,8 +209,7 @@ packetize_data(void *data, size_t length) return rc; } -static int -do_packet_read(char *data, struct list_head *ptemp_list, +static int do_packet_read(char *data, struct list_head *ptemp_list, int length, int bytes_read, int *list_read_count) { void *ptemp_buf; @@ -248,8 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list, return bytes_copied; } -static int -packet_read_list(char *data, size_t * pread_length) +static int packet_read_list(char *data, size_t *pread_length) { struct list_head *ptemp_list; int temp_count = 0; @@ -287,8 +281,7 @@ packet_read_list(char *data, size_t * pread_length) return 0; } -static void -packet_empty_list(void) +static void packet_empty_list(void) { struct list_head *ptemp_list; struct list_head *pnext_list; @@ -320,8 +313,7 @@ packet_empty_list(void) * img_update_free: Frees the buffer allocated for storing BIOS image * Always called with lock held and returned with lock held */ -static void -img_update_free(void) +static void img_update_free(void) { if (!rbu_data.image_update_buffer) return; @@ -358,8 +350,7 @@ img_update_free(void) * already allocated size, then that memory is reused. This function is * called with lock held and returns with lock held. */ -static int -img_update_realloc(unsigned long size) +static int img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; unsigned long rc; @@ -428,8 +419,7 @@ img_update_realloc(unsigned long size) return rc; } -static ssize_t -read_packet_data(char *buffer, loff_t pos, size_t count) +static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) { int retval; size_t bytes_left; @@ -470,8 +460,7 @@ read_packet_data(char *buffer, loff_t pos, size_t count) return retval; } -static ssize_t -read_rbu_mono_data(char *buffer, loff_t pos, size_t count) +static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) { unsigned char *ptemp = NULL; size_t bytes_left = 0; @@ -509,8 +498,8 @@ read_rbu_mono_data(char *buffer, loff_t pos, size_t count) return ret_count; } -static ssize_t -read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) +static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -527,8 +516,7 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) return ret_count; } -static void -callbackfn_rbu(const struct firmware *fw, void *context) +static void callbackfn_rbu(const struct firmware *fw, void *context) { int rc = 0; @@ -564,9 +552,8 @@ callbackfn_rbu(const struct firmware *fw, void *context) rbu_data.entry_created = 1; } -static ssize_t -read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) +static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) { int size = 0; if (!pos) @@ -574,9 +561,8 @@ read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, return size; } -static ssize_t -write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, - size_t count) +static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; @@ -636,18 +622,25 @@ write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, } static struct bin_attribute rbu_data_attr = { - .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, + .attr = { + .name = "data", + .owner = THIS_MODULE, + .mode = 0444, + }, .read = read_rbu_data, }; static struct bin_attribute rbu_image_type_attr = { - .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, + .attr = { + .name = "image_type", + .owner = THIS_MODULE, + .mode = 0644, + }, .read = read_rbu_image_type, .write = write_rbu_image_type, }; -static int __init -dcdrbu_init(void) +static int __init dcdrbu_init(void) { int rc = 0; spin_lock_init(&rbu_data.lock); @@ -677,8 +670,7 @@ dcdrbu_init(void) } -static __exit void -dcdrbu_exit(void) +static __exit void dcdrbu_exit(void) { spin_lock(&rbu_data.lock); packet_empty_list(); -- cgit v0.10.2 From 53d2be79d5981b7efc8c5ec1169613bba95bde20 Mon Sep 17 00:00:00 2001 From: Davide Libenzi Date: Fri, 16 Sep 2005 19:28:06 -0700 Subject: [PATCH] epoll: fix delayed initialization bug Al found a potential problem in epoll_create(), where the file->private_data member was set after fd_install(). This is obviously wrong since another thread might do a close() on that fd# before we set the file->private_data member. This goes over 2.6.13 and passes a few basic tests I've done here. (akpm: snuck in a kzalloc() cleanup too) Signed-off-by: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6ab1dd0..403b90a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -231,8 +231,9 @@ struct ep_pqueue { static void ep_poll_safewake_init(struct poll_safewake *psw); static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); -static int ep_getfd(int *efd, struct inode **einode, struct file **efile); -static int ep_file_init(struct file *file); +static int ep_getfd(int *efd, struct inode **einode, struct file **efile, + struct eventpoll *ep); +static int ep_alloc(struct eventpoll **pep); static void ep_free(struct eventpoll *ep); static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); static void ep_use_epitem(struct epitem *epi); @@ -501,38 +502,37 @@ void eventpoll_release_file(struct file *file) asmlinkage long sys_epoll_create(int size) { int error, fd; + struct eventpoll *ep; struct inode *inode; struct file *file; DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", current, size)); - /* Sanity check on the size parameter */ + /* + * Sanity check on the size parameter, and create the internal data + * structure ( "struct eventpoll" ). + */ error = -EINVAL; - if (size <= 0) + if (size <= 0 || (error = ep_alloc(&ep)) != 0) goto eexit_1; /* * Creates all the items needed to setup an eventpoll file. That is, * a file structure, and inode and a free file descriptor. */ - error = ep_getfd(&fd, &inode, &file); - if (error) - goto eexit_1; - - /* Setup the file internal data structure ( "struct eventpoll" ) */ - error = ep_file_init(file); + error = ep_getfd(&fd, &inode, &file, ep); if (error) goto eexit_2; - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, fd)); return fd; eexit_2: - sys_close(fd); + ep_free(ep); + kfree(ep); eexit_1: DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", current, size, error)); @@ -706,7 +706,8 @@ eexit_1: /* * Creates the file descriptor to be used by the epoll interface. */ -static int ep_getfd(int *efd, struct inode **einode, struct file **efile) +static int ep_getfd(int *efd, struct inode **einode, struct file **efile, + struct eventpoll *ep) { struct qstr this; char name[32]; @@ -756,7 +757,7 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile) file->f_op = &eventpoll_fops; file->f_mode = FMODE_READ; file->f_version = 0; - file->private_data = NULL; + file->private_data = ep; /* Install the new setup file into the allocated fd. */ fd_install(fd, file); @@ -777,14 +778,13 @@ eexit_1: } -static int ep_file_init(struct file *file) +static int ep_alloc(struct eventpoll **pep) { - struct eventpoll *ep; + struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); - if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL))) + if (!ep) return -ENOMEM; - memset(ep, 0, sizeof(*ep)); rwlock_init(&ep->lock); init_rwsem(&ep->sem); init_waitqueue_head(&ep->wq); @@ -792,9 +792,9 @@ static int ep_file_init(struct file *file) INIT_LIST_HEAD(&ep->rdllist); ep->rbr = RB_ROOT; - file->private_data = ep; + *pep = ep; - DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n", + DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", current, ep)); return 0; } -- cgit v0.10.2 From 393ad299658d8464149820363ee09bdf3fd45566 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 16 Sep 2005 19:28:07 -0700 Subject: [PATCH] hdaps driver update - Remove the relative input device - Add an absolute input device - Misc. cleanup and bug fixing The patch is sizable due to the cleanup from removing the relative input device (net -112 lines). Signed-off-by: Robert Love Cc: Dmitry Torokhov Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index eaebfc1..4c56411 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -5,10 +5,10 @@ * Copyright (C) 2005 Jesper Juhl * * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad - * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis - * accelerometer and other data, such as the device's temperature. + * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic + * two-axis accelerometer and other data, such as the device's temperature. * - * Based on the document by Mark A. Smith available at + * This driver is based on the document by Mark A. Smith available at * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial * and error. * @@ -36,12 +36,7 @@ #include #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ -#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */ - -#define STATE_FRESH 0x50 /* accelerometer data is fresh */ - -#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */ -#define REFRESH_SYNC 0x01 /* do synchronous refresh */ +#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */ #define HDAPS_PORT_STATE 0x1611 /* device state */ #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ @@ -53,7 +48,7 @@ #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ -#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */ +#define STATE_FRESH 0x50 /* accelerometer data is fresh */ #define KEYBD_MASK 0x20 /* set if keyboard activity */ #define MOUSE_MASK 0x40 /* set if mouse activity */ @@ -63,12 +58,11 @@ #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ -static struct platform_device *pdev; -static struct input_dev hdaps_idev; +#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ +#define HDAPS_INPUT_FUZZ 4 /* input event threshold */ + static struct timer_list hdaps_timer; -static unsigned int hdaps_mousedev_threshold = 4; -static unsigned long hdaps_poll_ms = 50; -static unsigned int hdaps_mousedev; +static struct platform_device *pdev; static unsigned int hdaps_invert; static u8 km_activity; static int rest_x; @@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem); */ static inline u8 __get_latch(u16 port) { - return inb(port) & HDAPS_READ_MASK; + return inb(port) & 0xff; } /* - * __check_latch - Check a port latch for a given value. Callers must hold - * hdaps_sem. Returns zero if the port contains the given value. + * __check_latch - Check a port latch for a given value. Returns zero if the + * port contains the given value. Callers must hold hdaps_sem. */ -static inline unsigned int __check_latch(u16 port, u8 val) +static inline int __check_latch(u16 port, u8 val) { if (__get_latch(port) == val) return 0; @@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val) * __wait_latch - Wait up to 100us for a port latch to get a certain value, * returning zero if the value is obtained. Callers must hold hdaps_sem. */ -static unsigned int __wait_latch(u16 port, u8 val) +static int __wait_latch(u16 port, u8 val) { unsigned int i; @@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val) udelay(5); } - return -EINVAL; + return -EIO; } /* - * __device_refresh - Request a refresh from the accelerometer. - * - * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait. - * Returns zero if successful and nonzero on error. - * - * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is - * not up-to-date. Always returns zero. - * - * Callers must hold hdaps_sem. + * __device_refresh - request a refresh from the accelerometer. Does not wait + * for refresh to complete. Callers must hold hdaps_sem. */ -static int __device_refresh(unsigned int sync) +static void __device_refresh(void) { - u8 state; - - udelay(100); - - state = inb(0x1604); - if (state == STATE_FRESH) - return 0; - - outb(0x11, 0x1610); - outb(0x01, 0x161f); - if (sync == REFRESH_ASYNC) - return 0; + udelay(200); + if (inb(0x1604) != STATE_FRESH) { + outb(0x11, 0x1610); + outb(0x01, 0x161f); + } +} +/* + * __device_refresh_sync - request a synchronous refresh from the + * accelerometer. We wait for the refresh to complete. Returns zero if + * successful and nonzero on error. Callers must hold hdaps_sem. + */ +static int __device_refresh_sync(void) +{ + __device_refresh(); return __wait_latch(0x1604, STATE_FRESH); } /* - * __device_complete - Indicate to the accelerometer that we are done reading + * __device_complete - indicate to the accelerometer that we are done reading * data, and then initiate an async refresh. Callers must hold hdaps_sem. */ static inline void __device_complete(void) { inb(0x161f); inb(0x1604); - __device_refresh(REFRESH_ASYNC); -} - -static int __hdaps_readb_one(unsigned int port, u8 *val) -{ - /* do a sync refresh -- we need to be sure that we read fresh data */ - if (__device_refresh(REFRESH_SYNC)) - return -EIO; - - *val = inb(port); - __device_complete(); - - return 0; + __device_refresh(); } /* @@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val) int ret; down(&hdaps_sem); - ret = __hdaps_readb_one(port, val); - up(&hdaps_sem); + /* do a sync refresh -- we need to be sure that we read fresh data */ + ret = __device_refresh_sync(); + if (ret) + goto out; + + *val = inb(port); + __device_complete(); + +out: + up(&hdaps_sem); return ret; } +/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */ static int __hdaps_read_pair(unsigned int port1, unsigned int port2, int *x, int *y) { /* do a sync refresh -- we need to be sure that we read fresh data */ - if (__device_refresh(REFRESH_SYNC)) + if (__device_refresh_sync()) return -EIO; *y = inw(port2); @@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, return ret; } -/* initialize the accelerometer */ +/* + * hdaps_device_init - initialize the accelerometer. Returns zero on success + * and negative error code on failure. Can sleep. + */ static int hdaps_device_init(void) { - unsigned int total_msecs = INIT_TIMEOUT_MSECS; - int ret = -ENXIO; + int total, ret = -ENXIO; down(&hdaps_sem); @@ -231,8 +219,10 @@ static int hdaps_device_init(void) goto out; /* - * The 0x03 value appears to only work on some thinkpads, such as the - * T42p. Others return 0x01. + * Most ThinkPads return 0x01. + * + * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops + * have "inverted" axises. * * The 0x02 value occurs when the chip has been previously initialized. */ @@ -267,24 +257,23 @@ static int hdaps_device_init(void) outb(0x01, 0x161f); if (__wait_latch(0x161f, 0x00)) goto out; - if (__device_refresh(REFRESH_SYNC)) + if (__device_refresh_sync()) goto out; if (__wait_latch(0x1611, 0x00)) goto out; /* we have done our dance, now let's wait for the applause */ - while (total_msecs > 0) { - u8 ignored; + for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { + int x, y; /* a read of the device helps push it into action */ - __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored); + __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); if (!__wait_latch(0x1611, 0x02)) { ret = 0; break; } msleep(INIT_WAIT_MSECS); - total_msecs -= INIT_WAIT_MSECS; } out: @@ -293,96 +282,6 @@ out: } -/* Input class stuff */ - -/* - * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem. - */ -static void hdaps_calibrate(void) -{ - int x, y; - - if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) - return; - - rest_x = x; - rest_y = y; -} - -static void hdaps_mousedev_poll(unsigned long unused) -{ - int x, y; - - /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ - if (down_trylock(&hdaps_sem)) { - mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms)); - return; - } - - if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) - goto out; - - x -= rest_x; - y -= rest_y; - if (abs(x) > hdaps_mousedev_threshold) - input_report_rel(&hdaps_idev, REL_X, x); - if (abs(y) > hdaps_mousedev_threshold) - input_report_rel(&hdaps_idev, REL_Y, y); - input_sync(&hdaps_idev); - - mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms)); - -out: - up(&hdaps_sem); -} - -/* - * hdaps_mousedev_enable - enable the input class device. Can sleep. - */ -static void hdaps_mousedev_enable(void) -{ - down(&hdaps_sem); - - /* calibrate the device before enabling */ - hdaps_calibrate(); - - /* initialize the input class */ - init_input_dev(&hdaps_idev); - hdaps_idev.dev = &pdev->dev; - hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); - hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT); - input_register_device(&hdaps_idev); - - /* start up our timer */ - init_timer(&hdaps_timer); - hdaps_timer.function = hdaps_mousedev_poll; - hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms); - add_timer(&hdaps_timer); - - hdaps_mousedev = 1; - - up(&hdaps_sem); - - printk(KERN_INFO "hdaps: input device enabled.\n"); -} - -/* - * hdaps_mousedev_disable - disable the input class device. Caller must hold - * hdaps_sem. - */ -static void hdaps_mousedev_disable(void) -{ - down(&hdaps_sem); - if (hdaps_mousedev) { - hdaps_mousedev = 0; - del_timer_sync(&hdaps_timer); - input_unregister_device(&hdaps_idev); - } - up(&hdaps_sem); -} - - /* Device model stuff */ static int hdaps_probe(struct device *dev) @@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = { .resume = hdaps_resume }; +/* Input class stuff */ + +static struct input_dev hdaps_idev = { + .name = "hdaps", + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, + .absmin = { [ABS_X] = -256, [ABS_Y] = -256 }, + .absmax = { [ABS_X] = 256, [ABS_Y] = 256 }, + .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, + .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, +}; + +/* + * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. + */ +static void hdaps_calibrate(void) +{ + __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); +} + +static void hdaps_mousedev_poll(unsigned long unused) +{ + int x, y; + + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ + if (down_trylock(&hdaps_sem)) { + mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); + return; + } + + if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) + goto out; + + input_report_abs(&hdaps_idev, ABS_X, x - rest_x); + input_report_abs(&hdaps_idev, ABS_Y, y - rest_y); + input_sync(&hdaps_idev); + + mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); + +out: + up(&hdaps_sem); +} + /* Sysfs Files */ @@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev, return count; } -static ssize_t hdaps_mousedev_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", hdaps_mousedev); -} - -static ssize_t hdaps_mousedev_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int enable; - - if (sscanf(buf, "%d", &enable) != 1) - return -EINVAL; - - if (enable == 1) - hdaps_mousedev_enable(); - else if (enable == 0) - hdaps_mousedev_disable(); - else - return -EINVAL; - - return count; -} - -static ssize_t hdaps_poll_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lu\n", hdaps_poll_ms); -} - -static ssize_t hdaps_poll_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int poll; - - if (sscanf(buf, "%u", &poll) != 1 || poll == 0) - return -EINVAL; - hdaps_poll_ms = poll; - - return count; -} - -static ssize_t hdaps_threshold_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", hdaps_mousedev_threshold); -} - -static ssize_t hdaps_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int threshold; - - if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0) - return -EINVAL; - hdaps_mousedev_threshold = threshold; - - return count; -} - static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); @@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL); static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); -static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store); -static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store); -static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show, - hdaps_threshold_store); static struct attribute *hdaps_attributes[] = { &dev_attr_position.attr, @@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = { &dev_attr_keyboard_activity.attr, &dev_attr_mouse_activity.attr, &dev_attr_calibrate.attr, - &dev_attr_mousedev.attr, - &dev_attr_mousedev_threshold.attr, - &dev_attr_mousedev_poll_ms.attr, &dev_attr_invert.attr, NULL, }; @@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = { * XXX: We should be able to return nonzero and halt the detection process. * But there is a bug in dmi_check_system() where a nonzero return from the * first match will result in a return of failure from dmi_check_system(). - * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make + * I fixed this; the patch is 2.6-git. Once in a released tree, we can make * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. */ static int hdaps_dmi_match(struct dmi_system_id *id) @@ -668,6 +540,7 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), { .ident = NULL } }; @@ -696,8 +569,18 @@ static int __init hdaps_init(void) if (ret) goto out_device; - if (hdaps_mousedev) - hdaps_mousedev_enable(); + /* initial calibrate for the input device */ + hdaps_calibrate(); + + /* initialize the input class */ + hdaps_idev.dev = &pdev->dev; + input_register_device(&hdaps_idev); + + /* start up our timer for the input device */ + init_timer(&hdaps_timer); + hdaps_timer.function = hdaps_mousedev_poll; + hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; + add_timer(&hdaps_timer); printk(KERN_INFO "hdaps: driver successfully loaded.\n"); return 0; @@ -715,8 +598,8 @@ out: static void __exit hdaps_exit(void) { - hdaps_mousedev_disable(); - + del_timer_sync(&hdaps_timer); + input_unregister_device(&hdaps_idev); sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); platform_device_unregister(pdev); driver_unregister(&hdaps_driver); @@ -728,9 +611,6 @@ static void __exit hdaps_exit(void) module_init(hdaps_init); module_exit(hdaps_exit); -module_param_named(mousedev, hdaps_mousedev, bool, 0); -MODULE_PARM_DESC(mousedev, "enable the input class device"); - module_param_named(invert, hdaps_invert, bool, 0); MODULE_PARM_DESC(invert, "invert data along each axis"); -- cgit v0.10.2 From 8ac2120d90273c590cf7662f03d103519101685b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 16 Sep 2005 19:28:08 -0700 Subject: [PATCH] i2c: kill an unused i2c_adapter struct member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kill an unused member of the i2c_adapter structure. This additionally fixes a potential bug, because doesn't include , so different files including could see a different definition of the i2c_adapter structure, depending on them including (or other header files themselves including ) before , or not. Credits go to Jörn Engel for pointing me to the problem. Signed-off-by: Jean Delvare Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/i2c.h b/include/linux/i2c.h index be35332..3d49a30 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -230,11 +230,6 @@ struct i2c_adapter { struct device dev; /* the adapter device */ struct class_device class_dev; /* the class device */ -#ifdef CONFIG_PROC_FS - /* No need to set this when you initialize the adapter */ - int inode; -#endif /* def CONFIG_PROC_FS */ - int nr; struct list_head clients; struct list_head list; -- cgit v0.10.2 From a464adeb7e8f1cd65ca911e20a7c02e452dc2c17 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 16 Sep 2005 19:28:09 -0700 Subject: [PATCH] Add smp_mb__after_clear_bit() to unlock_kiocb() Add smp_mb__after_clear_bit() to unlock_kiocb() AIO's use of wait_on_bit_lock()/wake_up_bit() forgot to add a barrier between clearing its lock bit and calling wake_up_bit() so wake_up_bit()'s unlocked waitqueue_active() can race. This puts AIO's use in line with the others and the comment above wake_up_bit(). Signed-off-by: Zach Brown Acked-by: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/aio.c b/fs/aio.c index 38f6268..0e11e31 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -562,6 +562,7 @@ static inline void lock_kiocb(struct kiocb *iocb) static inline void unlock_kiocb(struct kiocb *iocb) { kiocbClearLocked(iocb); + smp_mb__after_clear_bit(); wake_up_bit(&iocb->ki_flags, KIF_LOCKED); } -- cgit v0.10.2 From f647e08a55d2c88c4e7ab17a0a8e3fcf568fbc65 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 16 Sep 2005 19:28:10 -0700 Subject: [PATCH] joystick-vs-x.org fix Fix http://bugzilla.kernel.org/show_bug.cgi?id=5241 2.6.13 broke compilation of the xorg tree, which apprarently insists on including that file. Cc: Vojtech Pavlik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/joystick.h b/include/linux/joystick.h index 06b9af7..5fd20dd 100644 --- a/include/linux/joystick.h +++ b/include/linux/joystick.h @@ -111,29 +111,30 @@ struct js_corr { #define JS_SET_ALL 8 struct JS_DATA_TYPE { - __s32 buttons; - __s32 x; - __s32 y; + int32_t buttons; + int32_t x; + int32_t y; }; struct JS_DATA_SAVE_TYPE_32 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s32 JS_EXPIRETIME; - __s32 JS_TIMELIMIT; + int32_t JS_TIMEOUT; + int32_t BUSY; + int32_t JS_EXPIRETIME; + int32_t JS_TIMELIMIT; struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_CORR; }; struct JS_DATA_SAVE_TYPE_64 { - __s32 JS_TIMEOUT; - __s32 BUSY; - __s64 JS_EXPIRETIME; - __s64 JS_TIMELIMIT; + int32_t JS_TIMEOUT; + int32_t BUSY; + int64_t JS_EXPIRETIME; + int64_t JS_TIMELIMIT; struct JS_DATA_TYPE JS_SAVE; struct JS_DATA_TYPE JS_CORR; }; +#ifdef __KERNEL__ #if BITS_PER_LONG == 64 #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 #elif BITS_PER_LONG == 32 @@ -141,5 +142,6 @@ struct JS_DATA_SAVE_TYPE_64 { #else #error Unexpected BITS_PER_LONG #endif +#endif #endif /* _LINUX_JOYSTICK_H */ -- cgit v0.10.2 From af4e5a218e18ad588d60a4f9d6f8fb5db1a32587 Mon Sep 17 00:00:00 2001 From: Pekka J Enberg Date: Fri, 16 Sep 2005 19:28:11 -0700 Subject: [PATCH] CodingStyle: memory allocation This patch adds a new chapter on memory allocation to Documentation/CodingStyle. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 22e5f90..eb7db3c 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -410,7 +410,26 @@ Kernel messages do not have to be terminated with a period. Printing numbers in parentheses (%d) adds no value and should be avoided. - Chapter 13: References + Chapter 13: Allocating memory + +The kernel provides the following general purpose memory allocators: +kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API +documentation for further information about them. + +The preferred form for passing a size of a struct is the following: + + p = kmalloc(sizeof(*p), ...); + +The alternative form where struct name is spelled out hurts readability and +introduces an opportunity for a bug when the pointer variable type is changed +but the corresponding sizeof that is passed to a memory allocator is not. + +Casting the return value which is a void pointer is redundant. The conversion +from void pointer to any other pointer type is guaranteed by the C programming +language. + + + Chapter 14: References The C Programming Language, Second Edition by Brian W. Kernighan and Dennis M. Ritchie. -- cgit v0.10.2 From 4fb3a53860cee2aaaf81186c451b7da0b95b45c1 Mon Sep 17 00:00:00 2001 From: Dipankar Sarma Date: Fri, 16 Sep 2005 19:28:13 -0700 Subject: [PATCH] files: fix preemption issues With the new fdtable locking rules, you have to protect fdtable with either ->file_lock or rcu_read_lock/unlock(). There are some places where we aren't doing either. This patch fixes those places. Signed-off-by: Dipankar Sarma Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0636116..01fe990d 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, long timeout; int ret = -EINVAL; struct fdtable *fdt; + int max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, } } + rcu_read_lock(); fdt = files_fdtable(current->files); - if (n < 0 || n > fdt->max_fdset) + max_fdset = fdt->max_fdset; + rcu_read_unlock(); + if (n < 0 || n > max_fdset) goto out_nofds; /* diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index af42cda..d71731e 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -2218,12 +2218,13 @@ static void pfm_free_fd(int fd, struct file *file) { struct files_struct *files = current->files; - struct fdtable *fdt = files_fdtable(files); + struct fdtable *fdt; /* * there ie no fd_uninstall(), so we do it here */ spin_lock(&files->file_lock); + fdt = files_fdtable(files); rcu_assign_pointer(fdt->fd[fd], NULL); spin_unlock(&files->file_lock); diff --git a/fs/locks.c b/fs/locks.c index c2c09b4..f7daa5f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -124,6 +124,7 @@ #include #include #include +#include #include #include @@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from) lock_kernel(); j = 0; + rcu_read_lock(); fdt = files_fdtable(files); for (;;) { unsigned long set; @@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from) set >>= 1; } } + rcu_read_unlock(); unlock_kernel(); } EXPORT_SYMBOL(steal_locks); diff --git a/fs/proc/array.c b/fs/proc/array.c index d88d518..d84eeca 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer) p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); task_lock(p); + rcu_read_lock(); if (p->files) fdt = files_fdtable(p->files); buffer += sprintf(buffer, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); + rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); diff --git a/kernel/exit.c b/kernel/exit.c index 6d2089a..ee6d8b8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files) struct fdtable *fdt; j = 0; + + /* + * It is safe to dereference the fd table without RCU or + * ->file_lock because this is the last reference to the + * files structure. + */ fdt = files_fdtable(files); for (;;) { unsigned long set; -- cgit v0.10.2 From ef402268f7c9ab1872cafa1e638eb78a75b7c18f Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 16 Sep 2005 19:28:13 -0700 Subject: [PATCH] FAT: miss-sync issues on sync mount (miss-sync on write) This patch fixes miss-sync issue on write() system call. This updates inode attrs flags, mtime and ctime on every comit_write call, due to locking. Signed-off-by: Hiroyuki Machida Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/file.c b/fs/fat/file.c index 62ffa91..7134403 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -12,39 +12,6 @@ #include #include -static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf, - size_t count, loff_t pos) -{ - struct inode *inode = iocb->ki_filp->f_dentry->d_inode; - int retval; - - retval = generic_file_aio_write(iocb, buf, count, pos); - if (retval > 0) { - inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - MSDOS_I(inode)->i_attrs |= ATTR_ARCH; - mark_inode_dirty(inode); -// check the locking rules -// if (IS_SYNC(inode)) -// fat_sync_inode(inode); - } - return retval; -} - -static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov, - unsigned long nr_segs, loff_t *ppos) -{ - struct inode *inode = filp->f_dentry->d_inode; - int retval; - - retval = generic_file_writev(filp, iov, nr_segs, ppos); - if (retval > 0) { - inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - MSDOS_I(inode)->i_attrs |= ATTR_ARCH; - mark_inode_dirty(inode); - } - return retval; -} - int fat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -148,9 +115,9 @@ struct file_operations fat_file_operations = { .read = do_sync_read, .write = do_sync_write, .readv = generic_file_readv, - .writev = fat_file_writev, + .writev = generic_file_writev, .aio_read = generic_file_aio_read, - .aio_write = fat_file_aio_write, + .aio_write = generic_file_aio_write, .mmap = generic_file_mmap, .ioctl = fat_generic_ioctl, .fsync = file_fsync, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a7cbe68..51b1d15 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -102,6 +102,19 @@ static int fat_prepare_write(struct file *file, struct page *page, &MSDOS_I(page->mapping->host)->mmu_private); } +static int fat_commit_write(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + struct inode *inode = page->mapping->host; + int err = generic_commit_write(file, page, from, to); + if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + MSDOS_I(inode)->i_attrs |= ATTR_ARCH; + mark_inode_dirty(inode); + } + return err; +} + static sector_t _fat_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping, block, fat_get_block); @@ -112,7 +125,7 @@ static struct address_space_operations fat_aops = { .writepage = fat_writepage, .sync_page = block_sync_page, .prepare_write = fat_prepare_write, - .commit_write = generic_commit_write, + .commit_write = fat_commit_write, .bmap = _fat_bmap }; -- cgit v0.10.2 From 9564df1ff3c61f41bdc54283715417ccdfb6782b Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 16 Sep 2005 19:28:15 -0700 Subject: [PATCH] fix pf request handling Here's the patch from http://bugzilla.kernel.org/show_bug.cgi?id=4853 It is a feeble attempt at fixing the request handling in pf, it is totally foobar right now. Signed-off-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 711d2f3..94af920 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -750,6 +750,14 @@ static int pf_ready(void) static struct request_queue *pf_queue; +static void pf_end_request(int uptodate) +{ + if (pf_req) { + end_request(pf_req, uptodate); + pf_req = NULL; + } +} + static void do_pf_request(request_queue_t * q) { if (pf_busy) @@ -765,7 +773,7 @@ repeat: pf_count = pf_req->current_nr_sectors; if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { - end_request(pf_req, 0); + pf_end_request(0); goto repeat; } @@ -780,7 +788,7 @@ repeat: pi_do_claimed(pf_current->pi, do_pf_write); else { pf_busy = 0; - end_request(pf_req, 0); + pf_end_request(0); goto repeat; } } @@ -798,9 +806,11 @@ static int pf_next_buf(void) if (!pf_count) return 1; spin_lock_irqsave(&pf_spin_lock, saved_flags); - end_request(pf_req, 1); - pf_count = pf_req->current_nr_sectors; - pf_buf = pf_req->buffer; + pf_end_request(1); + if (pf_req) { + pf_count = pf_req->current_nr_sectors; + pf_buf = pf_req->buffer; + } spin_unlock_irqrestore(&pf_spin_lock, saved_flags); return 1; } @@ -810,7 +820,7 @@ static inline void next_request(int success) unsigned long saved_flags; spin_lock_irqsave(&pf_spin_lock, saved_flags); - end_request(pf_req, success); + pf_end_request(success); pf_busy = 0; do_pf_request(pf_queue); spin_unlock_irqrestore(&pf_spin_lock, saved_flags); -- cgit v0.10.2 From ef0f6a437f92fbd96c725086555b37b29371e107 Mon Sep 17 00:00:00 2001 From: Timothy Thelin Date: Fri, 16 Sep 2005 19:28:16 -0700 Subject: [PATCH] ide: fix null request pointer for taskfile ioctl When doing ioctl HDIO_DRIVE_TASKFILE, the ide_task_t's request pointer is never set, but flagged_taskfile and do_rw_taskfile pass it as a parameter to the prehandler. The kernel will oops taskfile pio-out commands because of this (taskfile pio-in doesn't use a prehandler). This fix sets the request pointer at the time the request is created to stop this oops. Signed-off-by: Timothy Thelin Cc: "Bartlomiej Zolnierkiewicz" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d04f62a..ace8eda 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long } rq.special = args; + args->rq = &rq; return ide_do_drive_cmd(drive, &rq, ide_wait); } -- cgit v0.10.2 From d648daca1170945600756b31866d0362a67f2aae Mon Sep 17 00:00:00 2001 From: Adam Kropelin Date: Fri, 16 Sep 2005 19:28:17 -0700 Subject: [PATCH] ibmphp: Use dword accessors for PCI_ROM_ADDRESS PCI_ROM_ADDRESS is a 32 bit register and as such should be accessed using pci_bus_{read,write}_config_dword(). A recent audit of drivers/ turned up several cases of byte- and word-sized accesses. The harmful ones were fixed by Linus directly. This patches up one of the remaining harmless-but-still-wrong cases caught in the dragnet. Signed-off-by: Adam Kropelin Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 8122fe7..b1ba429 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func) pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); - pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); return 0; -- cgit v0.10.2 From c2fa4f4ad8ddf4b9fac344f1da7a25d4868f08f5 Mon Sep 17 00:00:00 2001 From: Adam Kropelin Date: Fri, 16 Sep 2005 19:28:18 -0700 Subject: [PATCH] pciehp: Use dword accessors for PCI_ROM_ADDRESS PCI_ROM_ADDRESS is a 32 bit register and as such should be accessed using pci_bus_{read,write}_config_dword(). A recent audit of drivers/ turned up several cases of byte- and word-sized accesses. The harmful ones were fixed by Linus directly. This patches up one of the remaining harmless-but-still-wrong cases caught in the dragnet. Signed-off-by: Adam Kropelin Cc: Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0e09476..898f6da 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, int cloop; u8 temp_byte; u8 class_code; - u16 temp_word; u32 rc; u32 temp_register; u32 base; @@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, } /* End of base register loop */ /* disable ROM base Address */ - temp_word = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); /* Set HP parameters (Cache Line Size, Latency Timer) */ rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); -- cgit v0.10.2 From 06c6d271f41ffa20f2dadc9bfe100a89f7f1dd1d Mon Sep 17 00:00:00 2001 From: Adam Kropelin Date: Fri, 16 Sep 2005 19:28:19 -0700 Subject: [PATCH] shpchp: Use dword accessors for PCI_ROM_ADDRESS PCI_ROM_ADDRESS is a 32 bit register and as such should be accessed using pci_bus_{read,write}_config_dword(). A recent audit of drivers/ turned up several cases of byte- and word-sized accesses. The harmful ones were fixed by Linus directly. This patches up one of the remaining harmless-but-still-wrong cases caught in the dragnet. Signed-off-by: Adam Kropelin Cc: Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 783b5ab..91c9903 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -2824,8 +2824,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f } #endif /* Disable ROM base Address */ - temp_word = 0x00L; - rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); /* Set HP parameters (Cache Line Size, Latency Timer) */ rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); -- cgit v0.10.2 From 27b2f6792f3b482e4636818c7efaf4c43fef32a3 Mon Sep 17 00:00:00 2001 From: Adam Kropelin Date: Fri, 16 Sep 2005 19:28:20 -0700 Subject: [PATCH] qla2xxx: Use dword accessors for PCI_ROM_ADDRESS PCI_ROM_ADDRESS is a 32 bit register and as such should be accessed using pci_bus_{read,write}_config_dword(). A recent audit of drivers/ turned up several cases of byte- and word-sized accesses. The harmful ones were fixed by Linus directly. This patches up one of the remaining harmless-but-still-wrong cases caught in the dragnet. Signed-off-by: Adam Kropelin Cc: Andrew Vasquez Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3e9b641..23d095d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -201,6 +201,7 @@ int qla2100_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha) pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -237,6 +238,7 @@ int qla2300_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha) pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -324,6 +326,7 @@ int qla24xx_pci_config(scsi_qla_host_t *ha) { uint16_t w, mwi; + uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; int pcix_cmd_reg, pcie_dctl_reg; @@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha) } /* Reset expansion ROM address decode enable */ - pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); - w &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); -- cgit v0.10.2 From b95be99d52ce4f9db9ff0bd5f10e9e2066da6d2e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 15 Sep 2005 13:52:51 -0400 Subject: [SCSI] fix oops in scsi_release_buffers() I found one other thing that needs to be fixed. The call to scsi_release_buffers in scsi_unprep_request causes an oops, because the sgtable has already been freed in scsi_io_completion. The following patch is needed. Signed-off-by: Alan Stern Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0c6924e..f065cbc 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req) req->flags &= ~REQ_DONTPREP; req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; - scsi_release_buffers(cmd); scsi_put_command(cmd); } @@ -1512,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q) * cases (host limits or settings) should run the queue at some * later time. */ - scsi_unprep_request(req); spin_lock_irq(q->queue_lock); blk_requeue_request(q, req); sdev->device_busy--; -- cgit v0.10.2 From 61ffcafafb3d985e1ab8463be0187b421614775c Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Sat, 17 Sep 2005 23:52:42 +0200 Subject: [PATCH] Fix ST 5481 USB driver The old driver was not fully adapted to new USB ABI and does not work. Signed-off-by: Karsten Keil Signed-off-by: Linus Torvalds diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 0fda5c8..9ffaae7 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h @@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter); #define __debug_variable st5481_debug #include "hisax_debug.h" -#ifdef CONFIG_HISAX_DEBUG - extern int st5481_debug; +#ifdef CONFIG_HISAX_DEBUG + #define DBG_ISO_PACKET(level,urb) \ if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 2fcd093..0a2536d 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs) test_and_clear_bit(buf_nr, &b_out->busy); if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - if (b_out->busy == 0) { - st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); - } - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(4,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + if (b_out->busy == 0) { + st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); + } + break; } } @@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) bcs->mode = mode; // Cancel all USB transfers on this B channel + b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[0]); + b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[1]); b_out->busy = 0; diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 071b1d3..941f702 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs) test_and_clear_bit(buf_nr, &d_out->busy); if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - if (d_out->busy == 0) { - st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); - } - return; - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + break; + default: + WARN("urb status %d",urb->status); + if (d_out->busy == 0) { + st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); + } + break; } + return; // Give up } FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); @@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter) adapter->l1m.fsm = &l1fsm; adapter->l1m.state = ST_L1_F3; - adapter->l1m.debug = 1; + adapter->l1m.debug = st5481_debug & 0x100; adapter->l1m.userdata = adapter; adapter->l1m.printdebug = l1m_debug; FsmInitTimer(&adapter->l1m, &adapter->timer); adapter->d_out.fsm.fsm = &dout_fsm; adapter->d_out.fsm.state = ST_DOUT_NONE; - adapter->d_out.fsm.debug = 1; + adapter->d_out.fsm.debug = st5481_debug & 0x100; adapter->d_out.fsm.userdata = adapter; adapter->d_out.fsm.printdebug = dout_debug; diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 7aa810d..2cf5d1a 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */ module_param(number_of_leds, int, 0); #ifdef CONFIG_HISAX_DEBUG -static int debug = 0x1; +static int debug = 0; module_param(debug, int, 0); -int st5481_debug; #endif +int st5481_debug; static LIST_HEAD(adapter_list); diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index ab62223..ffd5b2d 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs) struct ctrl_msg *ctrl_msg; if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + break; } } @@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs) int status; switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - DBG(1, "urb shutting down with status: %d", urb->status); - return; - default: - WARN("nonzero urb status received: %d", urb->status); - goto exit; + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + DBG(2, "urb shutting down with status: %d", urb->status); + return; + default: + WARN("nonzero urb status received: %d", urb->status); + goto exit; } - DBG_PACKET(1, data, INT_PKT_SIZE); + DBG_PACKET(2, data, INT_PKT_SIZE); if (urb->actual_length == 0) { goto exit; @@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) struct urb *urb; u8 *buf; - DBG(1,""); + DBG(2,""); if ((status = usb_reset_configuration (dev)) < 0) { WARN("reset_configuration failed,status=%d",status); @@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter) DBG(1,""); // Stop and free Control and Interrupt URBs - usb_unlink_urb(ctrl->urb); + usb_kill_urb(ctrl->urb); if (ctrl->urb->transfer_buffer) kfree(ctrl->urb->transfer_buffer); usb_free_urb(ctrl->urb); + ctrl->urb = NULL; - usb_unlink_urb(intr->urb); + usb_kill_urb(intr->urb); if (intr->urb->transfer_buffer) kfree(intr->urb->transfer_buffer); usb_free_urb(intr->urb); + ctrl->urb = NULL; } /* @@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, spin_lock_init(&urb->lock); urb->dev=dev; urb->pipe=pipe; + urb->interval = 1; urb->transfer_buffer=buf; urb->number_of_packets = num_packets; urb->transfer_buffer_length=num_packets*packet_size; @@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, if (urb[j]) { if (urb[j]->transfer_buffer) kfree(urb[j]->transfer_buffer); + urb[j]->transfer_buffer = NULL; usb_free_urb(urb[j]); + urb[j] = NULL; } } return retval; @@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2]) int j; for (j = 0; j < 2; j++) { - usb_unlink_urb(urb[j]); + usb_kill_urb(urb[j]); if (urb[j]->transfer_buffer) kfree(urb[j]->transfer_buffer); usb_free_urb(urb[j]); + urb[j] = NULL; } } @@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs) int len, count, status; if (unlikely(urb->status < 0)) { - if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { - WARN("urb status %d",urb->status); - } else { - DBG(1,"urb killed"); - return; // Give up + switch (urb->status) { + case -ENOENT: + case -ESHUTDOWN: + case -ECONNRESET: + DBG(1,"urb killed status %d", urb->status); + return; // Give up + default: + WARN("urb status %d",urb->status); + break; } } @@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode) in->mode = mode; + in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[0]); + in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[1]); if (in->mode != L1_MODE_NULL) { -- cgit v0.10.2 From bc5e8fdfc622b03acf5ac974a1b8b26da6511c99 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 17 Sep 2005 15:41:04 -0700 Subject: x86-64/smp: fix random SIGSEGV issues They seem to have been due to AMD errata 63/122; the fix is to disable TLB flush filtering in SMP configurations. Confirmed to fix the problem by Andrew Walrond [ Let's see if we'll have a better fix eventually, this is the Q&D "let's get this fixed and out there" version ] Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 351d8d6..238f73e 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -831,11 +831,26 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) #endif } +#define HWCR 0xc0010015 + static int __init init_amd(struct cpuinfo_x86 *c) { int r; int level; +#ifdef CONFIG_SMP + unsigned long value; + + // Disable TLB flush filter by setting HWCR.FFDIS: + // bit 6 of msr C001_0015 + // + // Errata 63 for SH-B3 steppings + // Errata 122 for all(?) steppings + rdmsrl(HWCR, value); + value |= 1 << 6; + wrmsrl(HWCR, value); +#endif + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); -- cgit v0.10.2 From ae31c3399d17b1f7bc1742724f70476b5417744f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 18 Sep 2005 00:17:51 -0700 Subject: [DCCP]: Move the ack vector code to net/dccp/ackvec.[ch] Isolating it, that will be used when we introduce a CCID2 (TCP-Like) implementation. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 0e72708..8c8e029 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -353,14 +353,8 @@ static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) extern struct inet_timewait_death_row dccp_death_row; -/* Read about the ECN nonce to see why it is 253 */ -#define DCCP_MAX_ACK_VECTOR_LEN 253 - struct dccp_options_received { - u32 dccpor_ndp:24, - dccpor_ack_vector_len:8; - u32 dccpor_ack_vector_idx:10; - /* 22 bits hole, try to pack */ + u32 dccpor_ndp; /* only 24 bits */ u32 dccpor_timestamp; u32 dccpor_timestamp_echo; u32 dccpor_elapsed_time; @@ -394,6 +388,8 @@ static inline int dccp_list_has_service(const struct dccp_service_list *sl, return 0; } +struct dccp_ackvec; + /** * struct dccp_sock - DCCP socket state * @@ -414,7 +410,7 @@ static inline int dccp_list_has_service(const struct dccp_service_list *sl, * @dccps_packet_size - Set thru setsockopt * @dccps_role - Role of this sock, one of %dccp_role * @dccps_ndp_count - number of Non Data Packets since last data packet - * @dccps_hc_rx_ackpkts - receiver half connection acked packets + * @dccps_hc_rx_ackvec - rx half connection ack vector */ struct dccp_sock { /* inet_connection_sock has to be the first member of dccp_sock */ @@ -439,7 +435,7 @@ struct dccp_sock { __u32 dccps_pmtu_cookie; __u32 dccps_mss_cache; struct dccp_options dccps_options; - struct dccp_ackpkts *dccps_hc_rx_ackpkts; + struct dccp_ackvec *dccps_hc_rx_ackvec; void *dccps_hc_rx_ccid_private; void *dccps_hc_tx_ccid_private; struct ccid *dccps_hc_rx_ccid; diff --git a/net/dccp/Makefile b/net/dccp/Makefile index fb97bb0..344a8da 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile @@ -3,6 +3,8 @@ obj-$(CONFIG_IP_DCCP) += dccp.o dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ timer.o +dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o + obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o dccp_diag-y := diag.o diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c new file mode 100644 index 0000000..6530283 --- /dev/null +++ b/net/dccp/ackvec.c @@ -0,0 +1,419 @@ +/* + * net/dccp/ackvec.c + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Arnaldo Carvalho de Melo + * + * 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; version 2 of the License; + */ + +#include "ackvec.h" +#include "dccp.h" + +#include +#include + +#include + +int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; + int len = av->dccpav_vec_len + 2; + struct timeval now; + u32 elapsed_time; + unsigned char *to, *from; + + dccp_timestamp(sk, &now); + elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; + + if (elapsed_time != 0) + dccp_insert_option_elapsed_time(sk, skb, elapsed_time); + + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) + return -1; + + /* + * XXX: now we have just one ack vector sent record, so + * we have to wait for it to be cleared. + * + * Of course this is not acceptable, but this is just for + * basic testing now. + */ + if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1) + return -1; + + DCCP_SKB_CB(skb)->dccpd_opt_len += len; + + to = skb_push(skb, len); + *to++ = DCCPO_ACK_VECTOR_0; + *to++ = len; + + len = av->dccpav_vec_len; + from = av->dccpav_buf + av->dccpav_buf_head; + + /* Check if buf_head wraps */ + if (av->dccpav_buf_head + len > av->dccpav_vec_len) { + const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head); + + memcpy(to, from, tailsize); + to += tailsize; + len -= tailsize; + from = av->dccpav_buf; + } + + memcpy(to, from, len); + /* + * From draft-ietf-dccp-spec-11.txt: + * + * For each acknowledgement it sends, the HC-Receiver will add an + * acknowledgement record. ack_seqno will equal the HC-Receiver + * sequence number it used for the ack packet; ack_ptr will equal + * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will + * equal buf_nonce. + * + * This implemention uses just one ack record for now. + */ + av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; + av->dccpav_ack_ptr = av->dccpav_buf_head; + av->dccpav_ack_ackno = av->dccpav_buf_ackno; + av->dccpav_ack_nonce = av->dccpav_buf_nonce; + av->dccpav_sent_len = av->dccpav_vec_len; + + dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " + "ack_ackno=%llu\n", + debug_prefix, av->dccpav_sent_len, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + return -1; +} + +struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, + const unsigned int __nocast priority) +{ + struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority); + + if (av != NULL) { + av->dccpav_buf_len = len; + av->dccpav_buf_head = + av->dccpav_buf_tail = av->dccpav_buf_len - 1; + av->dccpav_buf_ackno = + av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU; + av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; + av->dccpav_ack_ptr = 0; + av->dccpav_time.tv_sec = 0; + av->dccpav_time.tv_usec = 0; + av->dccpav_sent_len = av->dccpav_vec_len = 0; + } + + return av; +} + +void dccp_ackvec_free(struct dccp_ackvec *av) +{ + kfree(av); +} + +static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, + const unsigned int index) +{ + return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; +} + +static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, + const unsigned int index) +{ + return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; +} + +/* + * If several packets are missing, the HC-Receiver may prefer to enter multiple + * bytes with run length 0, rather than a single byte with a larger run length; + * this simplifies table updates if one of the missing packets arrives. + */ +static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, + const unsigned int packets, + const unsigned char state) +{ + unsigned int gap; + signed long new_head; + + if (av->dccpav_vec_len + packets > av->dccpav_buf_len) + return -ENOBUFS; + + gap = packets - 1; + new_head = av->dccpav_buf_head - packets; + + if (new_head < 0) { + if (gap > 0) { + memset(av->dccpav_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED, + gap + new_head + 1); + gap = -new_head; + } + new_head += av->dccpav_buf_len; + } + + av->dccpav_buf_head = new_head; + + if (gap > 0) + memset(av->dccpav_buf + av->dccpav_buf_head + 1, + DCCP_ACKVEC_STATE_NOT_RECEIVED, gap); + + av->dccpav_buf[av->dccpav_buf_head] = state; + av->dccpav_vec_len += packets; + return 0; +} + +/* + * Implements the draft-ietf-dccp-spec-11.txt Appendix A + */ +int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state) +{ + /* + * Check at the right places if the buffer is full, if it is, tell the + * caller to start dropping packets till the HC-Sender acks our ACK + * vectors, when we will free up space in dccpav_buf. + * + * We may well decide to do buffer compression, etc, but for now lets + * just drop. + * + * From Appendix A: + * + * Of course, the circular buffer may overflow, either when the + * HC-Sender is sending data at a very high rate, when the + * HC-Receiver's acknowledgements are not reaching the HC-Sender, + * or when the HC-Sender is forgetting to acknowledge those acks + * (so the HC-Receiver is unable to clean up old state). In this + * case, the HC-Receiver should either compress the buffer (by + * increasing run lengths when possible), transfer its state to + * a larger buffer, or, as a last resort, drop all received + * packets, without processing them whatsoever, until its buffer + * shrinks again. + */ + + /* See if this is the first ackno being inserted */ + if (av->dccpav_vec_len == 0) { + av->dccpav_buf[av->dccpav_buf_head] = state; + av->dccpav_vec_len = 1; + } else if (after48(ackno, av->dccpav_buf_ackno)) { + const u64 delta = dccp_delta_seqno(av->dccpav_buf_ackno, + ackno); + + /* + * Look if the state of this packet is the same as the + * previous ackno and if so if we can bump the head len. + */ + if (delta == 1 && + dccp_ackvec_state(av, av->dccpav_buf_head) == state && + (dccp_ackvec_len(av, av->dccpav_buf_head) < + DCCP_ACKVEC_LEN_MASK)) + av->dccpav_buf[av->dccpav_buf_head]++; + else if (dccp_ackvec_set_buf_head_state(av, delta, state)) + return -ENOBUFS; + } else { + /* + * A.1.2. Old Packets + * + * When a packet with Sequence Number S arrives, and + * S <= buf_ackno, the HC-Receiver will scan the table + * for the byte corresponding to S. (Indexing structures + * could reduce the complexity of this scan.) + */ + u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); + unsigned int index = av->dccpav_buf_head; + + while (1) { + const u8 len = dccp_ackvec_len(av, index); + const u8 state = dccp_ackvec_state(av, index); + /* + * valid packets not yet in dccpav_buf have a reserved + * entry, with a len equal to 0. + */ + if (state == DCCP_ACKVEC_STATE_NOT_RECEIVED && + len == 0 && delta == 0) { /* Found our + reserved seat! */ + dccp_pr_debug("Found %llu reserved seat!\n", + (unsigned long long)ackno); + av->dccpav_buf[index] = state; + goto out; + } + /* len == 0 means one packet */ + if (delta < len + 1) + goto out_duplicate; + + delta -= len + 1; + if (++index == av->dccpav_buf_len) + index = 0; + } + } + + av->dccpav_buf_ackno = ackno; + dccp_timestamp(sk, &av->dccpav_time); +out: + dccp_pr_debug(""); + return 0; + +out_duplicate: + /* Duplicate packet */ + dccp_pr_debug("Received a dup or already considered lost " + "packet: %llu\n", (unsigned long long)ackno); + return -EILSEQ; +} + +#ifdef CONFIG_IP_DCCP_DEBUG +void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) +{ + if (!dccp_debug) + return; + + printk("ACK vector len=%d, ackno=%llu |", len, + (unsigned long long)ackno); + + while (len--) { + const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; + const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; + + printk("%d,%d|", state, rl); + ++vector; + } + + printk("\n"); +} + +void dccp_ackvec_print(const struct dccp_ackvec *av) +{ + dccp_ackvector_print(av->dccpav_buf_ackno, + av->dccpav_buf + av->dccpav_buf_head, + av->dccpav_vec_len); +} +#endif + +static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av) +{ + /* + * As we're keeping track of the ack vector size (dccpav_vec_len) and + * the sent ack vector size (dccpav_sent_len) we don't need + * dccpav_buf_tail at all, but keep this code here as in the future + * we'll implement a vector of ack records, as suggested in + * draft-ietf-dccp-spec-11.txt Appendix A. -acme + */ +#if 0 + av->dccpav_buf_tail = av->dccpav_ack_ptr + 1; + if (av->dccpav_buf_tail >= av->dccpav_vec_len) + av->dccpav_buf_tail -= av->dccpav_vec_len; +#endif + av->dccpav_vec_len -= av->dccpav_sent_len; +} + +void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, + const u64 ackno) +{ + /* Check if we actually sent an ACK vector */ + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) + return; + + if (ackno == av->dccpav_ack_seqno) { +#ifdef CONFIG_IP_DCCP_DEBUG + struct dccp_sock *dp = dccp_sk(sk); + const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? + "CLIENT rx ack: " : "server rx ack: "; +#endif + dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " + "ack_ackno=%llu, ACKED!\n", + debug_prefix, 1, + (unsigned long long)av->dccpav_ack_seqno, + (unsigned long long)av->dccpav_ack_ackno); + dccp_ackvec_trow_away_ack_record(av); + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; + } +} + +static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, + struct sock *sk, u64 ackno, + const unsigned char len, + const unsigned char *vector) +{ + unsigned char i; + + /* Check if we actually sent an ACK vector */ + if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) + return; + /* + * We're in the receiver half connection, so if the received an ACK + * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're + * not interested. + * + * Extra explanation with example: + * + * if we received an ACK vector with ackno 50, it can only be acking + * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). + */ + /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */ + if (before48(ackno, av->dccpav_ack_seqno)) { + /* dccp_pr_debug_cat("yes\n"); */ + return; + } + /* dccp_pr_debug_cat("no\n"); */ + + i = len; + while (i--) { + const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; + u64 ackno_end_rl; + + dccp_set_seqno(&ackno_end_rl, ackno - rl); + + /* + * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, + * av->dccpav_ack_seqno, ackno); + */ + if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { + const u8 state = (*vector & + DCCP_ACKVEC_STATE_MASK) >> 6; + /* dccp_pr_debug_cat("yes\n"); */ + + if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { +#ifdef CONFIG_IP_DCCP_DEBUG + struct dccp_sock *dp = dccp_sk(sk); + const char *debug_prefix = + dp->dccps_role == DCCP_ROLE_CLIENT ? + "CLIENT rx ack: " : "server rx ack: "; +#endif + dccp_pr_debug("%sACK vector 0, len=%d, " + "ack_seqno=%llu, ack_ackno=%llu, " + "ACKED!\n", + debug_prefix, len, + (unsigned long long) + av->dccpav_ack_seqno, + (unsigned long long) + av->dccpav_ack_ackno); + dccp_ackvec_trow_away_ack_record(av); + } + /* + * If dccpav_ack_seqno was not received, no problem + * we'll send another ACK vector. + */ + av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; + break; + } + /* dccp_pr_debug_cat("no\n"); */ + + dccp_set_seqno(&ackno, ackno_end_rl - 1); + ++vector; + } +} + +int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len) +{ + if (len > DCCP_MAX_ACKVEC_LEN) + return -1; + + /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ + dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_ack_seq, + len, value); + return 0; +} diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h new file mode 100644 index 0000000..8ca51c9 --- /dev/null +++ b/net/dccp/ackvec.h @@ -0,0 +1,133 @@ +#ifndef _ACKVEC_H +#define _ACKVEC_H +/* + * net/dccp/ackvec.h + * + * An implementation of the DCCP protocol + * Copyright (c) 2005 Arnaldo Carvalho de Melo + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +/* Read about the ECN nonce to see why it is 253 */ +#define DCCP_MAX_ACKVEC_LEN 253 + +#define DCCP_ACKVEC_STATE_RECEIVED 0 +#define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) +#define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6) + +#define DCCP_ACKVEC_STATE_MASK 0xC0 /* 11000000 */ +#define DCCP_ACKVEC_LEN_MASK 0x3F /* 00111111 */ + +/** struct dccp_ackvec - ack vector + * + * This data structure is the one defined in the DCCP draft + * Appendix A. + * + * @dccpav_buf_head - circular buffer head + * @dccpav_buf_tail - circular buffer tail + * @dccpav_buf_ackno - ack # of the most recent packet acknowledgeable in the + * buffer (i.e. %dccpav_buf_head) + * @dccpav_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked + * by the buffer with State 0 + * + * Additionally, the HC-Receiver must keep some information about the + * Ack Vectors it has recently sent. For each packet sent carrying an + * Ack Vector, it remembers four variables: + * + * @dccpav_ack_seqno - the Sequence Number used for the packet + * (HC-Receiver seqno) + * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement. + * @dccpav_ack_ackno - the Acknowledgement Number used for the packet + * (HC-Sender seqno) + * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. + * + * @dccpav_buf_len - circular buffer length + * @dccpav_time - the time in usecs + * @dccpav_buf - circular buffer of acknowledgeable packets + */ +struct dccp_ackvec { + unsigned int dccpav_buf_head; + unsigned int dccpav_buf_tail; + u64 dccpav_buf_ackno; + u64 dccpav_ack_seqno; + u64 dccpav_ack_ackno; + unsigned int dccpav_ack_ptr; + unsigned int dccpav_sent_len; + unsigned int dccpav_vec_len; + unsigned int dccpav_buf_len; + struct timeval dccpav_time; + u8 dccpav_buf_nonce; + u8 dccpav_ack_nonce; + u8 dccpav_buf[0]; +}; + +struct sock; +struct sk_buff; + +#ifdef CONFIG_IP_DCCP_ACKVEC +extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, + const unsigned int __nocast priority); +extern void dccp_ackvec_free(struct dccp_ackvec *av); + +extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state); + +extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, + struct sock *sk, const u64 ackno); +extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len); + +extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); + +static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) +{ + return av->dccpav_sent_len != av->dccpav_vec_len; +} +#else /* CONFIG_IP_DCCP_ACKVEC */ +static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, + const unsigned int __nocast priority) +{ + return NULL; +} + +static inline void dccp_ackvec_free(struct dccp_ackvec *av) +{ +} + +static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, + const u64 ackno, const u8 state) +{ + return -1; +} + +static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, + struct sock *sk, const u64 ackno) +{ +} + +static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, + const u8 opt, const u8 *value, const u8 len) +{ + return -1; +} + +static inline int dccp_insert_option_ackvec(const struct sock *sk, + const struct sk_buff *skb) +{ + return -1; +} + +static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) +{ + return 0; +} +#endif /* CONFIG_IP_DCCP_ACKVEC */ +#endif /* _ACKVEC_H */ diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index be7a660..5871c02 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -17,6 +17,7 @@ #include #include #include +#include "ackvec.h" #ifdef CONFIG_IP_DCCP_DEBUG extern int dccp_debug; @@ -358,6 +359,17 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq) (dp->dccps_gss - dp->dccps_options.dccpo_sequence_window + 1)); } + +static inline int dccp_ack_pending(const struct sock *sk) +{ + const struct dccp_sock *dp = dccp_sk(sk); + return dp->dccps_timestamp_echo != 0 || +#ifdef CONFIG_IP_DCCP_ACKVEC + (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || +#endif + inet_csk_ack_scheduled(sk); +} extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); extern void dccp_insert_option_elapsed_time(struct sock *sk, @@ -371,65 +383,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, extern struct socket *dccp_ctl_socket; -#define DCCP_ACKPKTS_STATE_RECEIVED 0 -#define DCCP_ACKPKTS_STATE_ECN_MARKED (1 << 6) -#define DCCP_ACKPKTS_STATE_NOT_RECEIVED (3 << 6) - -#define DCCP_ACKPKTS_STATE_MASK 0xC0 /* 11000000 */ -#define DCCP_ACKPKTS_LEN_MASK 0x3F /* 00111111 */ - -/** struct dccp_ackpkts - acknowledgeable packets - * - * This data structure is the one defined in the DCCP draft - * Appendix A. - * - * @dccpap_buf_head - circular buffer head - * @dccpap_buf_tail - circular buffer tail - * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the - * buffer (i.e. %dccpap_buf_head) - * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked - * by the buffer with State 0 - * - * Additionally, the HC-Receiver must keep some information about the - * Ack Vectors it has recently sent. For each packet sent carrying an - * Ack Vector, it remembers four variables: - * - * @dccpap_ack_seqno - the Sequence Number used for the packet - * (HC-Receiver seqno) - * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement. - * @dccpap_ack_ackno - the Acknowledgement Number used for the packet - * (HC-Sender seqno) - * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. - * - * @dccpap_buf_len - circular buffer length - * @dccpap_time - the time in usecs - * @dccpap_buf - circular buffer of acknowledgeable packets - */ -struct dccp_ackpkts { - unsigned int dccpap_buf_head; - unsigned int dccpap_buf_tail; - u64 dccpap_buf_ackno; - u64 dccpap_ack_seqno; - u64 dccpap_ack_ackno; - unsigned int dccpap_ack_ptr; - unsigned int dccpap_buf_vector_len; - unsigned int dccpap_ack_vector_len; - unsigned int dccpap_buf_len; - struct timeval dccpap_time; - u8 dccpap_buf_nonce; - u8 dccpap_ack_nonce; - u8 dccpap_buf[0]; -}; - -extern struct dccp_ackpkts * - dccp_ackpkts_alloc(unsigned int len, - const unsigned int __nocast priority); -extern void dccp_ackpkts_free(struct dccp_ackpkts *ap); -extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, - u64 ackno, u8 state); -extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, - struct sock *sk, u64 ackno); - extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); static inline suseconds_t timeval_usecs(const struct timeval *tv) @@ -470,15 +423,4 @@ static inline void timeval_sub_usecs(struct timeval *tv, } } -#ifdef CONFIG_IP_DCCP_DEBUG -extern void dccp_ackvector_print(const u64 ackno, - const unsigned char *vector, int len); -extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap); -#else -static inline void dccp_ackvector_print(const u64 ackno, - const unsigned char *vector, - int len) { } -static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { } -#endif - #endif /* _DCCP_H */ diff --git a/net/dccp/input.c b/net/dccp/input.c index 062e9f8..1b6b2cb 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -16,6 +16,7 @@ #include +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -60,8 +61,8 @@ static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) struct dccp_sock *dp = dccp_sk(sk); if (dp->dccps_options.dccpo_send_ack_vector) - dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq); + dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_ack_seq); } static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) @@ -164,37 +165,11 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - /* - * FIXME: check ECN to see if we should use - * DCCP_ACKPKTS_STATE_ECN_MARKED - */ - if (dp->dccps_options.dccpo_send_ack_vector) { - struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKPKTS_STATE_RECEIVED)) { - LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " - "packets buffer full!\n"); - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - TCP_DELACK_MIN, - DCCP_RTO_MAX); - goto discard; - } - - /* - * FIXME: this activation is probably wrong, have to study more - * TCP delack machinery and how it fits into DCCP draft, but - * for now it kinda "works" 8) - */ - if (!inet_csk_ack_scheduled(sk)) { - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ, - DCCP_RTO_MAX); - } - } + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); @@ -495,29 +470,11 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); - /* - * FIXME: check ECN to see if we should use - * DCCP_ACKPKTS_STATE_ECN_MARKED - */ - if (dp->dccps_options.dccpo_send_ack_vector) { - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, - dcb->dccpd_seq, - DCCP_ACKPKTS_STATE_RECEIVED)) - goto discard; - /* - * FIXME: this activation is probably wrong, have to - * study more TCP delack machinery and how it fits into - * DCCP draft, but for now it kinda "works" 8) - */ - if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno == - DCCP_MAX_SEQNO + 1) && - !inet_csk_ack_scheduled(sk)) { - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - TCP_DELACK_MIN, - DCCP_RTO_MAX); - } - } + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; } /* diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 94a440b..82434e4 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -23,6 +23,7 @@ #include #include +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -1112,45 +1113,7 @@ int dccp_v4_rcv(struct sk_buff *skb) goto discard_it; dh = dccp_hdr(skb); -#if 0 - /* - * Use something like this to simulate some DATA/DATAACK loss to test - * dccp_ackpkts_add, you'll get something like this on a session that - * sends 10 DATA/DATAACK packets: - * - * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1| - * - * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet - * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets - * with the same state - * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet - * - * So... - * - * 281473596467422 was received - * 281473596467421 was not received - * 281473596467420 was received - * 281473596467419 was not received - * 281473596467418 was received - * 281473596467417 was not received - * 281473596467416 was received - * 281473596467415 was not received - * 281473596467414 was received - * 281473596467413 was received (this one was the 3way handshake - * RESPONSE) - * - */ - if (dh->dccph_type == DCCP_PKT_DATA || - dh->dccph_type == DCCP_PKT_DATAACK) { - static int discard = 0; - if (discard) { - discard = 0; - goto discard_it; - } - discard = 1; - } -#endif DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; @@ -1264,11 +1227,9 @@ static int dccp_v4_init_sock(struct sock *sk) do_gettimeofday(&dp->dccps_epoch); if (dp->dccps_options.dccpo_send_ack_vector) { - dp->dccps_hc_rx_ackpkts = - dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, - GFP_KERNEL); - - if (dp->dccps_hc_rx_ackpkts == NULL) + dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, + GFP_KERNEL); + if (dp->dccps_hc_rx_ackvec == NULL) return -ENOMEM; } @@ -1288,8 +1249,10 @@ static int dccp_v4_init_sock(struct sock *sk) dp->dccps_hc_tx_ccid == NULL) { ccid_exit(dp->dccps_hc_rx_ccid, sk); ccid_exit(dp->dccps_hc_tx_ccid, sk); - dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); - dp->dccps_hc_rx_ackpkts = NULL; + if (dp->dccps_options.dccpo_send_ack_vector) { + dccp_ackvec_free(dp->dccps_hc_rx_ackvec); + dp->dccps_hc_rx_ackvec = NULL; + } dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; return -ENOMEM; } @@ -1331,8 +1294,10 @@ static int dccp_v4_destroy_sock(struct sock *sk) ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); - dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); - dp->dccps_hc_rx_ackpkts = NULL; + if (dp->dccps_options.dccpo_send_ack_vector) { + dccp_ackvec_free(dp->dccps_hc_rx_ackvec); + dp->dccps_hc_rx_ackvec = NULL; + } ccid_exit(dp->dccps_hc_rx_ccid, sk); ccid_exit(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 933e10d..1393461 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -19,6 +19,7 @@ #include #include +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -94,23 +95,23 @@ struct sock *dccp_create_openreq_child(struct sock *sk, struct dccp_sock *newdp = dccp_sk(newsk); newdp->dccps_role = DCCP_ROLE_SERVER; - newdp->dccps_hc_rx_ackpkts = NULL; + newdp->dccps_hc_rx_ackvec = NULL; newdp->dccps_service_list = NULL; newdp->dccps_service = dreq->dreq_service; newicsk->icsk_rto = DCCP_TIMEOUT_INIT; do_gettimeofday(&newdp->dccps_epoch); if (newdp->dccps_options.dccpo_send_ack_vector) { - newdp->dccps_hc_rx_ackpkts = - dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, - GFP_ATOMIC); + newdp->dccps_hc_rx_ackvec = + dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, + GFP_ATOMIC); /* * XXX: We're using the same CCIDs set on the parent, * i.e. sk_clone copied the master sock and left the * CCID pointers for this child, that is why we do the * __ccid_get calls. */ - if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL)) + if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) goto out_free; } @@ -118,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, newsk) != 0 || ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, newsk) != 0)) { - dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts); + dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); out_free: diff --git a/net/dccp/options.c b/net/dccp/options.c index d4c4242..c480c50 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -18,15 +18,10 @@ #include #include +#include "ackvec.h" #include "ccid.h" #include "dccp.h" -static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, - struct sock *sk, - const u64 ackno, - const unsigned char len, - const unsigned char *vector); - /* stores the default values for new connection. may be changed with sysctl */ static const struct dccp_options dccpo_default_values = { .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, @@ -113,25 +108,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) opt_recv->dccpor_ndp); break; case DCCPO_ACK_VECTOR_0: - if (len > DCCP_MAX_ACK_VECTOR_LEN) - goto out_invalid_option; - + case DCCPO_ACK_VECTOR_1: if (pkt_type == DCCP_PKT_DATA) continue; - opt_recv->dccpor_ack_vector_len = len; - opt_recv->dccpor_ack_vector_idx = value - options; - - dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n", - debug_prefix, len, - (unsigned long long) - DCCP_SKB_CB(skb)->dccpd_ack_seq); - dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, - value, len); - dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts, - sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq, - len, value); + if (dp->dccps_options.dccpo_send_ack_vector && + dccp_ackvec_parse(sk, skb, opt, value, len)) + goto out_invalid_option; break; case DCCPO_TIMESTAMP: if (len != 4) @@ -352,86 +335,6 @@ void dccp_insert_option_elapsed_time(struct sock *sk, EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); -static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) -{ - struct dccp_sock *dp = dccp_sk(sk); -#ifdef CONFIG_IP_DCCP_DEBUG - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT TX opt: " : "server TX opt: "; -#endif - struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - int len = ap->dccpap_buf_vector_len + 2; - struct timeval now; - u32 elapsed_time; - unsigned char *to, *from; - - dccp_timestamp(sk, &now); - elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10; - - if (elapsed_time != 0) - dccp_insert_option_elapsed_time(sk, skb, elapsed_time); - - if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { - LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " - "insert ACK Vector!\n"); - return; - } - - /* - * XXX: now we have just one ack vector sent record, so - * we have to wait for it to be cleared. - * - * Of course this is not acceptable, but this is just for - * basic testing now. - */ - if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1) - return; - - DCCP_SKB_CB(skb)->dccpd_opt_len += len; - - to = skb_push(skb, len); - *to++ = DCCPO_ACK_VECTOR_0; - *to++ = len; - - len = ap->dccpap_buf_vector_len; - from = ap->dccpap_buf + ap->dccpap_buf_head; - - /* Check if buf_head wraps */ - if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) { - const unsigned int tailsize = (ap->dccpap_buf_len - - ap->dccpap_buf_head); - - memcpy(to, from, tailsize); - to += tailsize; - len -= tailsize; - from = ap->dccpap_buf; - } - - memcpy(to, from, len); - /* - * From draft-ietf-dccp-spec-11.txt: - * - * For each acknowledgement it sends, the HC-Receiver will add an - * acknowledgement record. ack_seqno will equal the HC-Receiver - * sequence number it used for the ack packet; ack_ptr will equal - * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will - * equal buf_nonce. - * - * This implemention uses just one ack record for now. - */ - ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; - ap->dccpap_ack_ptr = ap->dccpap_buf_head; - ap->dccpap_ack_ackno = ap->dccpap_buf_ackno; - ap->dccpap_ack_nonce = ap->dccpap_buf_nonce; - ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len; - - dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " - "ack_ackno=%llu\n", - debug_prefix, ap->dccpap_ack_vector_len, - (unsigned long long) ap->dccpap_ack_seqno, - (unsigned long long) ap->dccpap_ack_ackno); -} - void dccp_timestamp(const struct sock *sk, struct timeval *tv) { const struct dccp_sock *dp = dccp_sk(sk); @@ -528,9 +431,8 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) if (!dccp_packet_without_ack(skb)) { if (dp->dccps_options.dccpo_send_ack_vector && - (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != - DCCP_MAX_SEQNO + 1)) - dccp_insert_option_ack_vector(sk, skb); + dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) + dccp_insert_option_ackvec(sk, skb); if (dp->dccps_timestamp_echo != 0) dccp_insert_option_timestamp_echo(sk, skb); } @@ -557,331 +459,3 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) } } } - -struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len, - const unsigned int __nocast priority) -{ - struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority); - - if (ap != NULL) { -#ifdef CONFIG_IP_DCCP_DEBUG - memset(ap->dccpap_buf, 0xFF, len); -#endif - ap->dccpap_buf_len = len; - ap->dccpap_buf_head = - ap->dccpap_buf_tail = - ap->dccpap_buf_len - 1; - ap->dccpap_buf_ackno = - ap->dccpap_ack_ackno = - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0; - ap->dccpap_ack_ptr = 0; - ap->dccpap_time.tv_sec = 0; - ap->dccpap_time.tv_usec = 0; - ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0; - } - - return ap; -} - -void dccp_ackpkts_free(struct dccp_ackpkts *ap) -{ - if (ap != NULL) { -#ifdef CONFIG_IP_DCCP_DEBUG - memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len); -#endif - kfree(ap); - } -} - -static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap, - const unsigned int index) -{ - return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK; -} - -static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap, - const unsigned int index) -{ - return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK; -} - -/* - * If several packets are missing, the HC-Receiver may prefer to enter multiple - * bytes with run length 0, rather than a single byte with a larger run length; - * this simplifies table updates if one of the missing packets arrives. - */ -static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap, - const unsigned int packets, - const unsigned char state) -{ - unsigned int gap; - signed long new_head; - - if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len) - return -ENOBUFS; - - gap = packets - 1; - new_head = ap->dccpap_buf_head - packets; - - if (new_head < 0) { - if (gap > 0) { - memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED, - gap + new_head + 1); - gap = -new_head; - } - new_head += ap->dccpap_buf_len; - } - - ap->dccpap_buf_head = new_head; - - if (gap > 0) - memset(ap->dccpap_buf + ap->dccpap_buf_head + 1, - DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap); - - ap->dccpap_buf[ap->dccpap_buf_head] = state; - ap->dccpap_buf_vector_len += packets; - return 0; -} - -/* - * Implements the draft-ietf-dccp-spec-11.txt Appendix A - */ -int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, - u64 ackno, u8 state) -{ - /* - * Check at the right places if the buffer is full, if it is, tell the - * caller to start dropping packets till the HC-Sender acks our ACK - * vectors, when we will free up space in dccpap_buf. - * - * We may well decide to do buffer compression, etc, but for now lets - * just drop. - * - * From Appendix A: - * - * Of course, the circular buffer may overflow, either when the - * HC-Sender is sending data at a very high rate, when the - * HC-Receiver's acknowledgements are not reaching the HC-Sender, - * or when the HC-Sender is forgetting to acknowledge those acks - * (so the HC-Receiver is unable to clean up old state). In this - * case, the HC-Receiver should either compress the buffer (by - * increasing run lengths when possible), transfer its state to - * a larger buffer, or, as a last resort, drop all received - * packets, without processing them whatsoever, until its buffer - * shrinks again. - */ - - /* See if this is the first ackno being inserted */ - if (ap->dccpap_buf_vector_len == 0) { - ap->dccpap_buf[ap->dccpap_buf_head] = state; - ap->dccpap_buf_vector_len = 1; - } else if (after48(ackno, ap->dccpap_buf_ackno)) { - const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno, - ackno); - - /* - * Look if the state of this packet is the same as the - * previous ackno and if so if we can bump the head len. - */ - if (delta == 1 && - dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state && - (dccp_ackpkts_len(ap, ap->dccpap_buf_head) < - DCCP_ACKPKTS_LEN_MASK)) - ap->dccpap_buf[ap->dccpap_buf_head]++; - else if (dccp_ackpkts_set_buf_head_state(ap, delta, state)) - return -ENOBUFS; - } else { - /* - * A.1.2. Old Packets - * - * When a packet with Sequence Number S arrives, and - * S <= buf_ackno, the HC-Receiver will scan the table - * for the byte corresponding to S. (Indexing structures - * could reduce the complexity of this scan.) - */ - u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno); - unsigned int index = ap->dccpap_buf_head; - - while (1) { - const u8 len = dccp_ackpkts_len(ap, index); - const u8 state = dccp_ackpkts_state(ap, index); - /* - * valid packets not yet in dccpap_buf have a reserved - * entry, with a len equal to 0. - */ - if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED && - len == 0 && delta == 0) { /* Found our - reserved seat! */ - dccp_pr_debug("Found %llu reserved seat!\n", - (unsigned long long) ackno); - ap->dccpap_buf[index] = state; - goto out; - } - /* len == 0 means one packet */ - if (delta < len + 1) - goto out_duplicate; - - delta -= len + 1; - if (++index == ap->dccpap_buf_len) - index = 0; - } - } - - ap->dccpap_buf_ackno = ackno; - dccp_timestamp(sk, &ap->dccpap_time); -out: - dccp_pr_debug(""); - dccp_ackpkts_print(ap); - return 0; - -out_duplicate: - /* Duplicate packet */ - dccp_pr_debug("Received a dup or already considered lost " - "packet: %llu\n", (unsigned long long) ackno); - return -EILSEQ; -} - -#ifdef CONFIG_IP_DCCP_DEBUG -void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, - int len) -{ - if (!dccp_debug) - return; - - printk("ACK vector len=%d, ackno=%llu |", len, - (unsigned long long) ackno); - - while (len--) { - const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6; - const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); - - printk("%d,%d|", state, rl); - ++vector; - } - - printk("\n"); -} - -void dccp_ackpkts_print(const struct dccp_ackpkts *ap) -{ - dccp_ackvector_print(ap->dccpap_buf_ackno, - ap->dccpap_buf + ap->dccpap_buf_head, - ap->dccpap_buf_vector_len); -} -#endif - -static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap) -{ - /* - * As we're keeping track of the ack vector size - * (dccpap_buf_vector_len) and the sent ack vector size - * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but - * keep this code here as in the future we'll implement a vector of - * ack records, as suggested in draft-ietf-dccp-spec-11.txt - * Appendix A. -acme - */ -#if 0 - ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1; - if (ap->dccpap_buf_tail >= ap->dccpap_buf_len) - ap->dccpap_buf_tail -= ap->dccpap_buf_len; -#endif - ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len; -} - -void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk, - u64 ackno) -{ - /* Check if we actually sent an ACK vector */ - if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) - return; - - if (ackno == ap->dccpap_ack_seqno) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " - "ack_ackno=%llu, ACKED!\n", - debug_prefix, 1, - (unsigned long long) ap->dccpap_ack_seqno, - (unsigned long long) ap->dccpap_ack_ackno); - dccp_ackpkts_trow_away_ack_record(ap); - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - } -} - -static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, - struct sock *sk, u64 ackno, - const unsigned char len, - const unsigned char *vector) -{ - unsigned char i; - - /* Check if we actually sent an ACK vector */ - if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) - return; - /* - * We're in the receiver half connection, so if the received an ACK - * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're - * not interested. - * - * Extra explanation with example: - * - * if we received an ACK vector with ackno 50, it can only be acking - * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). - */ - /* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */ - if (before48(ackno, ap->dccpap_ack_seqno)) { - /* dccp_pr_debug_cat("yes\n"); */ - return; - } - /* dccp_pr_debug_cat("no\n"); */ - - i = len; - while (i--) { - const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); - u64 ackno_end_rl; - - dccp_set_seqno(&ackno_end_rl, ackno - rl); - - /* - * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, - * ap->dccpap_ack_seqno, ackno); - */ - if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) { - const u8 state = (*vector & - DCCP_ACKPKTS_STATE_MASK) >> 6; - /* dccp_pr_debug_cat("yes\n"); */ - - if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) { -#ifdef CONFIG_IP_DCCP_DEBUG - struct dccp_sock *dp = dccp_sk(sk); - const char *debug_prefix = - dp->dccps_role == DCCP_ROLE_CLIENT ? - "CLIENT rx ack: " : "server rx ack: "; -#endif - dccp_pr_debug("%sACK vector 0, len=%d, " - "ack_seqno=%llu, ack_ackno=%llu, " - "ACKED!\n", - debug_prefix, len, - (unsigned long long) - ap->dccpap_ack_seqno, - (unsigned long long) - ap->dccpap_ack_ackno); - dccp_ackpkts_trow_away_ack_record(ap); - } - /* - * If dccpap_ack_seqno was not received, no problem - * we'll send another ACK vector. - */ - ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; - break; - } - /* dccp_pr_debug_cat("no\n"); */ - - dccp_set_seqno(&ackno, ackno_end_rl - 1); - ++vector; - } -} diff --git a/net/dccp/output.c b/net/dccp/output.c index 156b1d2..4786bdc 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -16,6 +16,7 @@ #include +#include "ackvec.h" #include "ccid.h" #include "dccp.h" @@ -225,7 +226,6 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) err = dccp_wait_for_ccid(sk, skb, timeo); if (err == 0) { - const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); const int len = skb->len; @@ -236,15 +236,7 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); dcb->dccpd_type = DCCP_PKT_DATAACK; - /* - * FIXME: we really should have a - * dccps_ack_pending or use icsk. - */ - } else if (inet_csk_ack_scheduled(sk) || - dp->dccps_timestamp_echo != 0 || - (dp->dccps_options.dccpo_send_ack_vector && - ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && - ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) + } else if (dccp_ack_pending(sk)) dcb->dccpd_type = DCCP_PKT_DATAACK; else dcb->dccpd_type = DCCP_PKT_DATA; -- cgit v0.10.2 From 65299d6c3cfb49cc3eee4fc483e7edd23ea7b2ed Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 18 Sep 2005 00:18:32 -0700 Subject: [CCID3]: Introduce include/linux/tfrc.h Moving the TFRC sender and receiver variables to separate structs, so that we can copy these structs to userspace thru getsockopt, dccp_diag, etc. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h new file mode 100644 index 0000000..7dab783 --- /dev/null +++ b/include/linux/tfrc.h @@ -0,0 +1,35 @@ +#ifndef _LINUX_TFRC_H_ +#define _LINUX_TFRC_H_ +/* + * include/linux/tfrc.h + * + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. + * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005 Arnaldo Carvalho de Melo + * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon + * + * 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. + */ + +#include + +struct tfrc_rx_info { + __u32 tfrcrx_x_recv; + __u32 tfrcrx_rtt; + __u32 tfrcrx_p; +}; + +struct tfrc_tx_info { + __u32 tfrctx_x; + __u32 tfrctx_x_recv; + __u32 tfrctx_x_calc; + __u32 tfrctx_rtt; + __u32 tfrctx_p; + __u32 tfrctx_rto; + __u32 tfrctx_ipi; +}; + +#endif /* _LINUX_TFRC_H_ */ diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index eb24877..0bde458 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -40,6 +40,7 @@ #include #include #include +#include #define TFRC_MIN_PACKET_SIZE 16 #define TFRC_STD_PACKET_SIZE 256 @@ -93,12 +94,15 @@ struct ccid3_options_received { * @ccid3hctx_hist - Packet history */ struct ccid3_hc_tx_sock { - u32 ccid3hctx_x; - u32 ccid3hctx_x_recv; - u32 ccid3hctx_x_calc; + struct tfrc_tx_info ccid3hctx_tfrc; +#define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x +#define ccid3hctx_x_recv ccid3hctx_tfrc.tfrctx_x_recv +#define ccid3hctx_x_calc ccid3hctx_tfrc.tfrctx_x_calc +#define ccid3hctx_rtt ccid3hctx_tfrc.tfrctx_rtt +#define ccid3hctx_p ccid3hctx_tfrc.tfrctx_p +#define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto +#define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi u16 ccid3hctx_s; - u32 ccid3hctx_rtt; - u32 ccid3hctx_p; u8 ccid3hctx_state; u8 ccid3hctx_last_win_count; u8 ccid3hctx_idle; @@ -106,19 +110,19 @@ struct ccid3_hc_tx_sock { struct timer_list ccid3hctx_no_feedback_timer; struct timeval ccid3hctx_t_ld; struct timeval ccid3hctx_t_nom; - u32 ccid3hctx_t_rto; - u32 ccid3hctx_t_ipi; u32 ccid3hctx_delta; struct list_head ccid3hctx_hist; struct ccid3_options_received ccid3hctx_options_received; }; struct ccid3_hc_rx_sock { + struct tfrc_rx_info ccid3hcrx_tfrc; +#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv +#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt +#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p u64 ccid3hcrx_seqno_last_counter:48, ccid3hcrx_state:8, ccid3hcrx_last_counter:4; - u32 ccid3hcrx_rtt; - u32 ccid3hcrx_p; u32 ccid3hcrx_bytes_recv; struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_ack; @@ -127,7 +131,6 @@ struct ccid3_hc_rx_sock { u16 ccid3hcrx_s; u32 ccid3hcrx_pinv; u32 ccid3hcrx_elapsed_time; - u32 ccid3hcrx_x_recv; }; static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) -- cgit v0.10.2 From 561713cf475de1f671cc89c437927ec008a20209 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 18 Sep 2005 00:18:52 -0700 Subject: [DCCP]: Don't use necessarily the same CCID for tx and rx Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 8c8e029..13f9b78 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -330,7 +330,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) */ struct dccp_options { __u64 dccpo_sequence_window; - __u8 dccpo_ccid; + __u8 dccpo_rx_ccid; + __u8 dccpo_tx_ccid; __u8 dccpo_send_ack_vector; __u8 dccpo_send_ndp_count; }; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 82434e4..40fe6af 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1241,9 +1241,9 @@ static int dccp_v4_init_sock(struct sock *sk) * setsockopt(CCIDs-I-want/accept). -acme */ if (likely(!dccp_ctl_socket_init)) { - dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, + dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, sk); - dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, + dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, sk); if (dp->dccps_hc_rx_ccid == NULL || dp->dccps_hc_tx_ccid == NULL) { diff --git a/net/dccp/options.c b/net/dccp/options.c index c480c50..0a76426 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -25,7 +25,8 @@ /* stores the default values for new connection. may be changed with sysctl */ static const struct dccp_options dccpo_default_values = { .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, - .dccpo_ccid = DCCPF_INITIAL_CCID, + .dccpo_rx_ccid = DCCPF_INITIAL_CCID, + .dccpo_tx_ccid = DCCPF_INITIAL_CCID, .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, }; -- cgit v0.10.2 From 88f964db6ef728982734356bf4c406270ea29c1d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 18 Sep 2005 00:19:32 -0700 Subject: [DCCP]: Introduce CCID getsockopt for the CCIDs Allocation for the optnames is similar to the DCCP options, with a range for rx and tx half connection CCIDs. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 13f9b78..71fab43 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h @@ -179,6 +179,8 @@ enum { /* DCCP socket options */ #define DCCP_SOCKOPT_PACKET_SIZE 1 #define DCCP_SOCKOPT_SERVICE 2 +#define DCCP_SOCKOPT_CCID_RX_INFO 128 +#define DCCP_SOCKOPT_CCID_TX_INFO 192 #define DCCP_SERVICE_LIST_MAX_LEN 32 diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 962f1e9..21e5514 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -54,6 +55,14 @@ struct ccid { struct tcp_info *info); void (*ccid_hc_tx_get_info)(struct sock *sk, struct tcp_info *info); + int (*ccid_hc_rx_getsockopt)(struct sock *sk, + const int optname, int len, + u32 __user *optval, + int __user *optlen); + int (*ccid_hc_tx_getsockopt)(struct sock *sk, + const int optname, int len, + u32 __user *optval, + int __user *optlen); }; extern int ccid_register(struct ccid *ccid); @@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, if (ccid->ccid_hc_tx_get_info != NULL) ccid->ccid_hc_tx_get_info(sk, info); } + +static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, + const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + int rc = -ENOPROTOOPT; + if (ccid->ccid_hc_rx_getsockopt != NULL) + rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, + optval, optlen); + return rc; +} + +static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, + const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + int rc = -ENOPROTOOPT; + if (ccid->ccid_hc_tx_getsockopt != NULL) + rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, + optval, optlen); + return rc; +} #endif /* _CCID_H */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 38aa849..aa68e0a 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) info->tcpi_rtt = hctx->ccid3hctx_rtt; } +static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); + const void *val; + + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) + return -EINVAL; + + switch (optname) { + case DCCP_SOCKOPT_CCID_RX_INFO: + if (len < sizeof(hcrx->ccid3hcrx_tfrc)) + return -EINVAL; + len = sizeof(hcrx->ccid3hcrx_tfrc); + val = &hcrx->ccid3hcrx_tfrc; + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen) || copy_to_user(optval, val, len)) + return -EFAULT; + + return 0; +} + +static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, + u32 __user *optval, int __user *optlen) +{ + const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + const void *val; + + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) + return -EINVAL; + + switch (optname) { + case DCCP_SOCKOPT_CCID_TX_INFO: + if (len < sizeof(hctx->ccid3hctx_tfrc)) + return -EINVAL; + len = sizeof(hctx->ccid3hctx_tfrc); + val = &hctx->ccid3hctx_tfrc; + break; + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen) || copy_to_user(optval, val, len)) + return -EFAULT; + + return 0; +} + static struct ccid ccid3 = { .ccid_id = 3, .ccid_name = "ccid3", @@ -1139,6 +1193,8 @@ static struct ccid ccid3 = { .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, .ccid_hc_rx_get_info = ccid3_hc_rx_get_info, .ccid_hc_tx_get_info = ccid3_hc_tx_get_info, + .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, + .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, }; module_param(ccid3_debug, int, 0444); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 9bda286..a1cfd0e 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -325,12 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, if (get_user(len, optlen)) return -EFAULT; - if (optname == DCCP_SOCKOPT_SERVICE) - return dccp_getsockopt_service(sk, len, - (u32 __user *)optval, optlen); - - len = min_t(unsigned int, len, sizeof(int)); - if (len < 0) + if (len < sizeof(int)) return -EINVAL; dp = dccp_sk(sk); @@ -338,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, switch (optname) { case DCCP_SOCKOPT_PACKET_SIZE: val = dp->dccps_packet_size; + len = sizeof(dp->dccps_packet_size); break; + case DCCP_SOCKOPT_SERVICE: + return dccp_getsockopt_service(sk, len, + (u32 __user *)optval, optlen); + case 128 ... 191: + return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, + len, (u32 __user *)optval, optlen); + case 192 ... 255: + return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname, + len, (u32 __user *)optval, optlen); default: return -ENOPROTOOPT; } -- cgit v0.10.2 From 40abc27066c49b2c13c817154d438431b0303b96 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Sun, 18 Sep 2005 00:24:12 -0700 Subject: [BOND]: Fix bond_init() error path handling. From: Florin Malita bond_init() is not releasing rtnl_sem after register_netdevice() and before calling unregister_netdevice() (from bond_free_all()) in the exception path. As the device registration is not completed (dev->reg_state == NETREG_REGISTERING), the call to unregister_netdevice() triggers BUG_ON(dev->reg_state != NETREG_REGISTERED). Signed-off-by: Florin Malita Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f8dedb6..90449a0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5039,6 +5039,14 @@ static int __init bonding_init(void) return 0; out_err: + /* + * rtnl_unlock() will run netdev_run_todo(), putting the + * thus-far-registered bonding devices into a state which + * unregigister_netdevice() will accept + */ + rtnl_unlock(); + rtnl_lock(); + /* free and unregister all bonds that were successfully added */ bond_free_all(); -- cgit v0.10.2 From 987905ded3d19c196dae25cac46c569cac9594b8 Mon Sep 17 00:00:00 2001 From: Mitsuru KANDA Date: Sun, 18 Sep 2005 00:30:08 -0700 Subject: [IPV6]: Check connect(2) status for IPv6 UDP socket (Re: xfrm_lookup) I think we should cache the per-socket route(dst_entry) only when the IPv6 UDP socket is connect(2)'ed. (which is same as IPv4 UDP send behavior) Signed-off-by: Mitsuru KANDA Signed-off-by: David S. Miller diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 2b9bf9b..6001948 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -639,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, int tclass = -1; int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; int err; + int connected = 0; /* destination address check */ if (sin6) { @@ -748,6 +749,7 @@ do_udp_sendmsg: fl->fl_ip_dport = inet->dport; daddr = &np->daddr; fl->fl6_flowlabel = np->flow_label; + connected = 1; } if (!fl->oif) @@ -770,6 +772,7 @@ do_udp_sendmsg: } if (!(opt->opt_nflen|opt->opt_flen)) opt = NULL; + connected = 0; } if (opt == NULL) opt = np->opt; @@ -787,10 +790,13 @@ do_udp_sendmsg: ipv6_addr_copy(&final, &fl->fl6_dst); ipv6_addr_copy(&fl->fl6_dst, rt0->addr); final_p = &final; + connected = 0; } - if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) + if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { fl->oif = np->mcast_oif; + connected = 0; + } err = ip6_dst_lookup(sk, &dst, fl); if (err) @@ -846,7 +852,7 @@ do_append_data: else if (!corkreq) err = udp_v6_push_pending_frames(sk, up); - if (dst) + if (dst && connected) ip6_dst_store(sk, dst, ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? &np->daddr : NULL); -- cgit v0.10.2 From 628f87f3d585bd0c2b0e39df039585d7a5831cc9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 18 Sep 2005 00:33:02 -0700 Subject: [NETFILTER]: Solve Kconfig dependency problem As suggested by Roman Zippel. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 85190de..e2162d2 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -8,7 +8,6 @@ menu "IP: Netfilter Configuration" # connection tracking, helpers and protocols config IP_NF_CONNTRACK tristate "Connection tracking (required for masq/NAT)" - select NETFILTER_NETLINK if IP_NF_CONNTRACK_NETLINK!=n ---help--- Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related @@ -55,8 +54,7 @@ config IP_NF_CONNTRACK_EVENTS config IP_NF_CONNTRACK_NETLINK tristate 'Connection tracking netlink interface' depends on IP_NF_CONNTRACK && NETFILTER_NETLINK - default IP_NF_CONNTRACK if NETFILTER_NETLINK=y - default m if NETFILTER_NETLINK=m + depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m help This option enables support for a netlink-based userspace interface -- cgit v0.10.2 From 7f8c0fd78dccaf30e60cb4303bd7a21c7d9e6da3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Sep 2005 21:11:08 +0100 Subject: [ARM] Fix warning in asm/futex.h The recently added futex.h contains an unused variable, which gcc naturally warns about. Remove this unused variable. Signed-off-by: Russell King diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-arm/futex.h +++ b/include/asm-arm/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; -- cgit v0.10.2 From e0a200894efa33ea1ac9957717ae151afa02bb6f Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Sun, 18 Sep 2005 21:11:56 +0100 Subject: [ARM] 2917/1: Make IXP4xx mach_desc's depend on config options Patch from Deepak Saxena Building a kernel for IXDP425 currently includes the machine descriptors for IXDP465 and PRPMC1100 even if those machines are not configured. This means we can build a kernel that boots on those machines even though the machine_is_xxx() macro will always return 0 and other bits such as PCI won't be compiled in. This can lead to many wasted hours wondering what you have done to your kernel to make it randomly crash thus requireing large quantities of beer to be consumed. While I am all for consumption of large quantities of beer, there are better reasons to do so then stupid kernel bugs. Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index ae1fa09..39b06ed 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -123,6 +123,7 @@ static void __init ixdp425_init(void) platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); } +#ifdef CONFIG_ARCH_IXDP465 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -134,7 +135,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif +#ifdef CONFIG_MACH_IXDP465 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -146,7 +149,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif +#ifdef CONFIG_ARCH_PRPMC1100 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, @@ -158,6 +163,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") .boot_params = 0x0100, .init_machine = ixdp425_init, MACHINE_END +#endif /* * Avila is functionally equivalent to IXDP425 except that it adds -- cgit v0.10.2 From a64358db1253b35d508a411e80a3ad23b859ec88 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 26 Jul 2005 10:27:10 -0400 Subject: [SCSI] SCSI scanning and removal fixes This patch (as545) fixes the list traversals in __scsi_remove_target and scsi_forget_host. In each case the existing code list_for_each_entry_safe in an _unsafe_ manner, because the list was not protected from outside modification while the iteration was running. The new scsi_forget_host routine takes the moderately controversial step of iterating over devices for removal rather than iterating over targets. This makes more sense to me because the current scheme treats targets as second-class citizens, created and removed on demand, rather than as objects corresponding to actual hardware. (Also I couldn't figure out any safe way to iterate over the target list, since it's not so easy to tell when a target has already been removed.) Signed-off-by: Alan Stern Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b86f170..fcf9f6c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target); void scsi_forget_host(struct Scsi_Host *shost) { - struct scsi_target *starget, *tmp; + struct scsi_device *sdev; unsigned long flags; - /* - * Ok, this look a bit strange. We always look for the first device - * on the list as scsi_remove_device removes them from it - thus we - * also have to release the lock. - * We don't need to get another reference to the device before - * releasing the lock as we already own the reference from - * scsi_register_device that's release in scsi_remove_device. And - * after that we don't look at sdev anymore. - */ + restart: spin_lock_irqsave(shost->host_lock, flags); - list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) { + list_for_each_entry(sdev, &shost->__devices, siblings) { + if (sdev->sdev_state == SDEV_DEL) + continue; spin_unlock_irqrestore(shost->host_lock, flags); - scsi_remove_target(&starget->dev); - spin_lock_irqsave(shost->host_lock, flags); + __scsi_remove_device(sdev); + goto restart; } spin_unlock_irqrestore(shost->host_lock, flags); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 83f87c4..1e47b7e 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -719,17 +719,20 @@ void __scsi_remove_target(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; - struct scsi_device *sdev, *tmp; + struct scsi_device *sdev; spin_lock_irqsave(shost->host_lock, flags); starget->reap_ref++; - list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) { + restart: + list_for_each_entry(sdev, &shost->__devices, siblings) { if (sdev->channel != starget->channel || - sdev->id != starget->id) + sdev->id != starget->id || + sdev->sdev_state == SDEV_DEL) continue; spin_unlock_irqrestore(shost->host_lock, flags); scsi_remove_device(sdev); spin_lock_irqsave(shost->host_lock, flags); + goto restart; } spin_unlock_irqrestore(shost->host_lock, flags); scsi_target_reap(starget); -- cgit v0.10.2 From 63150fcf73dbfb752a850a5e2fe3aed570154433 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Sep 2005 21:49:29 +0100 Subject: [ARM] Fix warning in arch/arm/kernel/semaphore.c Newer binutils complains: /tmp/cc07pbI9.s:146: Warning: ignoring changed section type for .sched.text Fix this warning by adding %progbits to the .section. Signed-off-by: Russell King diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index ac423e3..4c31f29 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem) * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. */ -asm(" .section .sched.text,\"ax\" \n\ +asm(" .section .sched.text,\"ax\",%progbits \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ -- cgit v0.10.2 From 118ec0b3e02e7d22cf27b9f5a2836fa6f395b61a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Sep 2005 22:16:41 +0100 Subject: [ARM] Fix warning in arch/arm/mach-sa1100/generic.c Fix: arch/arm/mach-sa1100/generic.c:224: warning: 'struct mcp_plat_data' declared inside parameter list caused by mussing structure and function declaration. Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 279e3af..f085d68 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h @@ -39,3 +39,6 @@ extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops); struct irda_platform_data; void sa11x0_set_irda_data(struct irda_platform_data *irda); + +struct mcp_plat_data; +void sa11x0_set_mcp_data(struct mcp_plat_data *data); -- cgit v0.10.2 From 51574e0398a2d93cbf7f26e36b673cd919062268 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 12 Sep 2005 09:52:28 -0700 Subject: [PATCH] IPoIB: fix module removal race Since ipoib uses queue_delayed_work to run flush task on port state events, it must flush scheduled work after unregistering the event handler. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 49d120d..704f48e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1005,6 +1005,7 @@ debug_failed: register_failed: ib_unregister_event_handler(&priv->event_handler); + flush_scheduled_work(); event_failed: ipoib_dev_cleanup(priv->dev); @@ -1057,6 +1058,7 @@ static void ipoib_remove_one(struct ib_device *device) list_for_each_entry_safe(priv, tmp, dev_list, list) { ib_unregister_event_handler(&priv->event_handler); + flush_scheduled_work(); unregister_netdev(priv->dev); ipoib_dev_cleanup(priv->dev); -- cgit v0.10.2 From bb4a7f0da75ce9f3e933880428d39b2aa1f16961 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 12 Sep 2005 14:08:51 -0700 Subject: [PATCH] IB/mthca: assign ACK timeout field correctly The hardware reads the ACK timeout field from the most significant 5 bits of struct mthca_qp_path's ackto field, not the least significant bits. This fix has the driver put the timeout in the right place. Without this, we get a timeout that is 2^8 times too small. Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index bcef06b..2c883c1 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -687,7 +687,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) } if (attr_mask & IB_QP_TIMEOUT) { - qp_context->pri_path.ackto = attr->timeout; + qp_context->pri_path.ackto = attr->timeout << 3; qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); } -- cgit v0.10.2 From d6cff021e24515255b296d399ec517a68bf2ed08 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 13 Sep 2005 10:41:03 -0700 Subject: [PATCH] IB/mthca: fix posting of first work request Fix posting first WQE for mem-free HCAs: we need to link to previous WQE even in that case. While we're at it, simplify code for Tavor-mode HCAs. We don't really need the conditional test there either; we can similarly always link to the previous WQE. Based on Michael S. Tsirkin's analogous fix for userspace libmthca. Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 2c883c1..eaa5218 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -227,7 +227,6 @@ static void mthca_wq_init(struct mthca_wq *wq) wq->last_comp = wq->max - 1; wq->head = 0; wq->tail = 0; - wq->last = NULL; } void mthca_qp_event(struct mthca_dev *dev, u32 qpn, @@ -1103,6 +1102,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, } } + qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); + qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); + return 0; } @@ -1583,15 +1585,13 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - if (prev_wqe) { - ((struct mthca_next_seg *) prev_wqe)->nda_op = - cpu_to_be32(((ind << qp->sq.wqe_shift) + - qp->send_wqe_offset) | - mthca_opcode[wr->opcode]); - wmb(); - ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size); - } + ((struct mthca_next_seg *) prev_wqe)->nda_op = + cpu_to_be32(((ind << qp->sq.wqe_shift) + + qp->send_wqe_offset) | + mthca_opcode[wr->opcode]); + wmb(); + ((struct mthca_next_seg *) prev_wqe)->ee_nds = + cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size); if (!size0) { size0 = size; @@ -1688,13 +1688,11 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, qp->wrid[ind] = wr->wr_id; - if (likely(prev_wqe)) { - ((struct mthca_next_seg *) prev_wqe)->nda_op = - cpu_to_be32((ind << qp->rq.wqe_shift) | 1); - wmb(); - ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32(MTHCA_NEXT_DBD | size); - } + ((struct mthca_next_seg *) prev_wqe)->nda_op = + cpu_to_be32((ind << qp->rq.wqe_shift) | 1); + wmb(); + ((struct mthca_next_seg *) prev_wqe)->ee_nds = + cpu_to_be32(MTHCA_NEXT_DBD | size); if (!size0) size0 = size; @@ -1905,15 +1903,13 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, goto out; } - if (likely(prev_wqe)) { - ((struct mthca_next_seg *) prev_wqe)->nda_op = - cpu_to_be32(((ind << qp->sq.wqe_shift) + - qp->send_wqe_offset) | - mthca_opcode[wr->opcode]); - wmb(); - ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32(MTHCA_NEXT_DBD | size); - } + ((struct mthca_next_seg *) prev_wqe)->nda_op = + cpu_to_be32(((ind << qp->sq.wqe_shift) + + qp->send_wqe_offset) | + mthca_opcode[wr->opcode]); + wmb(); + ((struct mthca_next_seg *) prev_wqe)->ee_nds = + cpu_to_be32(MTHCA_NEXT_DBD | size); if (!size0) { size0 = size; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 75cd2d8..fe06cc0 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -189,7 +189,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->max = attr->max_wr; srq->max_gs = attr->max_sge; - srq->last = NULL; srq->counter = 0; if (mthca_is_memfree(dev)) @@ -264,6 +263,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->first_free = 0; srq->last_free = srq->max - 1; + srq->last = get_wqe(srq, srq->max - 1); return 0; @@ -446,13 +446,11 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, ((struct mthca_data_seg *) wqe)->addr = 0; } - if (likely(prev_wqe)) { - ((struct mthca_next_seg *) prev_wqe)->nda_op = - cpu_to_be32((ind << srq->wqe_shift) | 1); - wmb(); - ((struct mthca_next_seg *) prev_wqe)->ee_nds = - cpu_to_be32(MTHCA_NEXT_DBD); - } + ((struct mthca_next_seg *) prev_wqe)->nda_op = + cpu_to_be32((ind << srq->wqe_shift) | 1); + wmb(); + ((struct mthca_next_seg *) prev_wqe)->ee_nds = + cpu_to_be32(MTHCA_NEXT_DBD); srq->wrid[ind] = wr->wr_id; srq->first_free = next_ind; -- cgit v0.10.2 From ce5b65cc9626feac0d4ffb96f798407e50c45575 Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Sun, 18 Sep 2005 13:47:53 -0700 Subject: [PATCH] IPoIB: Fix SA client retransmission strategy We got a little mixed up with what the backoff member holds in the IPoIB multicast group structure: sometimes it was used as a number of seconds, and sometimes it was used as a number of jiffies. Fix the code so that backoff is always in seconds. Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index aca7aea..3aab4d8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -145,7 +145,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev, mcast->dev = dev; mcast->created = jiffies; - mcast->backoff = HZ; + mcast->backoff = 1; mcast->logcount = 0; INIT_LIST_HEAD(&mcast->list); @@ -396,7 +396,7 @@ static void ipoib_mcast_join_complete(int status, IPOIB_GID_ARG(mcast->mcmember.mgid), status); if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { - mcast->backoff = HZ; + mcast->backoff = 1; down(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_work(ipoib_workqueue, &priv->mcast_task); @@ -496,7 +496,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) queue_delayed_work(ipoib_workqueue, &priv->mcast_task, - mcast->backoff); + mcast->backoff * HZ); up(&mcast_mutex); } else mcast->query_id = ret; -- cgit v0.10.2 From c915033fc62d7186d243d89f88782d6be33fd8f6 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sun, 18 Sep 2005 13:52:06 -0700 Subject: [PATCH] IB/mthca: Initialize eq->nent before we use it In mthca_create_eq(), we call get_eqe() before setting eq->nent. This is wrong, because get_eqe() uses eq->nent. Fix this, and clean up the code a little while we're at it. (We got lucky with the current code, because eq->nent was cleared to 0, which get_eqe() made happen to do the right thing) Pointed out by Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 18f0981..78152a8 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -476,12 +476,8 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, int i; u8 status; - /* Make sure EQ size is aligned to a power of 2 size. */ - for (i = 1; i < nent; i <<= 1) - ; /* nothing */ - nent = i; - - eq->dev = dev; + eq->dev = dev; + eq->nent = roundup_pow_of_two(max(nent, 2)); eq->page_list = kmalloc(npages * sizeof *eq->page_list, GFP_KERNEL); @@ -512,7 +508,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, memset(eq->page_list[i].buf, 0, PAGE_SIZE); } - for (i = 0; i < nent; ++i) + for (i = 0; i < eq->nent; ++i) set_eqe_hw(get_eqe(eq, i)); eq->eqn = mthca_alloc(&dev->eq_table.alloc); @@ -528,8 +524,6 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, if (err) goto err_out_free_eq; - eq->nent = nent; - memset(eq_context, 0, sizeof *eq_context); eq_context->flags = cpu_to_be32(MTHCA_EQ_STATUS_OK | MTHCA_EQ_OWNER_HW | @@ -538,7 +532,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, if (mthca_is_memfree(dev)) eq_context->flags |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL); - eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24); + eq_context->logsize_usrpage = cpu_to_be32((ffs(eq->nent) - 1) << 24); if (mthca_is_memfree(dev)) { eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num); } else { @@ -569,7 +563,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, dev->eq_table.arm_mask |= eq->eqn_mask; mthca_dbg(dev, "Allocated EQ %d with %d entries\n", - eq->eqn, nent); + eq->eqn, eq->nent); return err; -- cgit v0.10.2 From 3853194c2e174cee4da093c67bd54cbf9a38559a Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sun, 18 Sep 2005 14:00:17 -0700 Subject: [PATCH] IB/mthca: Fix posting work requests to shared receive queues The error handling paths in mthca_tavor_post_srq_recv() and mthca_arbel_post_srq_recv() are quite bogus, the result of a screwed up merge. Fix them so they work as intended. Pointed out by Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index fe06cc0..45dedd2 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -409,7 +409,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, mthca_err(dev, "SRQ %06x full\n", srq->srqn); err = -ENOMEM; *bad_wr = wr; - return nreq; + break; } wqe = get_wqe(srq, ind); @@ -427,7 +427,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, err = -EINVAL; *bad_wr = wr; srq->last = prev_wqe; - return nreq; + break; } for (i = 0; i < wr->num_sge; ++i) { @@ -456,8 +456,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, srq->first_free = next_ind; } - return nreq; - if (likely(nreq)) { __be32 doorbell[2]; @@ -501,7 +499,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, mthca_err(dev, "SRQ %06x full\n", srq->srqn); err = -ENOMEM; *bad_wr = wr; - return nreq; + break; } wqe = get_wqe(srq, ind); @@ -517,7 +515,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, if (unlikely(wr->num_sge > srq->max_gs)) { err = -EINVAL; *bad_wr = wr; - return nreq; + break; } for (i = 0; i < wr->num_sge; ++i) { -- cgit v0.10.2 From 5c9f6de3b80ca46000bd1b63d892820f9ee32138 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 19 Sep 2005 09:33:40 +0100 Subject: NTFS: Fix various bugs in the runlist merging code. (Based on libntfs changes by Richard Russon.) Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 49eafbd..c7e9237 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -92,6 +92,8 @@ ToDo/Notes: an octal number to conform to how chmod(1) works, too. Thanks to Giuseppe Bilotta and Horst von Brand for pointing out the errors of my ways. + - Fix various bugs in the runlist merging code. (Based on libntfs + changes by Richard Russon.) 2.1.23 - Implement extension of resident files and make writing safe as well as many bug fixes, cleanups, and enhancements... diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index f5b2ac9..e2665d0 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -2,7 +2,7 @@ * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. * * Copyright (c) 2001-2005 Anton Altaparmakov - * Copyright (c) 2002 Richard Russon + * Copyright (c) 2002-2005 Richard Russon * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -214,8 +214,8 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src) static inline runlist_element *ntfs_rl_append(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL right; - int magic; + BOOL right; /* Right end of @src needs merging. */ + int marker; /* End of the inserted runs. */ BUG_ON(!dst); BUG_ON(!src); @@ -236,18 +236,19 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst, if (right) __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); - magic = loc + ssize; + /* First run after the @src runs that have been inserted. */ + marker = loc + ssize + 1; /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, magic + 1, loc + 1 + right, dsize - loc - 1 - right); + ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right)); ntfs_rl_mc(dst, loc + 1, src, 0, ssize); /* Adjust the size of the preceding hole. */ dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; /* We may have changed the length of the file, so fix the end marker */ - if (dst[magic + 1].lcn == LCN_ENOENT) - dst[magic + 1].vcn = dst[magic].vcn + dst[magic].length; + if (dst[marker].lcn == LCN_ENOENT) + dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; return dst; } @@ -279,18 +280,17 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst, static inline runlist_element *ntfs_rl_insert(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL left = FALSE; - BOOL disc = FALSE; /* Discontinuity */ - BOOL hole = FALSE; /* Following a hole */ - int magic; + BOOL left = FALSE; /* Left end of @src needs merging. */ + BOOL disc = FALSE; /* Discontinuity between @dst and @src. */ + int marker; /* End of the inserted runs. */ BUG_ON(!dst); BUG_ON(!src); - /* disc => Discontinuity between the end of @dst and the start of @src. - * This means we might need to insert a hole. - * hole => @dst ends with a hole or an unmapped region which we can - * extend to match the discontinuity. */ + /* + * disc => Discontinuity between the end of @dst and the start of @src. + * This means we might need to insert a "not mapped" run. + */ if (loc == 0) disc = (src[0].vcn > 0); else { @@ -303,58 +303,49 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst, merged_length += src->length; disc = (src[0].vcn > dst[loc - 1].vcn + merged_length); - if (disc) - hole = (dst[loc - 1].lcn == LCN_HOLE); } - - /* Space required: @dst size + @src size, less one if we merged, plus - * one if there was a discontinuity, less one for a trailing hole. */ - dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc - hole); + /* + * Space required: @dst size + @src size, less one if we merged, plus + * one if there was a discontinuity. + */ + dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc); if (IS_ERR(dst)) return dst; /* * We are guaranteed to succeed from here so can start modifying the * original runlist. */ - if (left) __ntfs_rl_merge(dst + loc - 1, src); - - magic = loc + ssize - left + disc - hole; + /* + * First run after the @src runs that have been inserted. + * Nominally, @marker equals @loc + @ssize, i.e. location + number of + * runs in @src. However, if @left, then the first run in @src has + * been merged with one in @dst. And if @disc, then @dst and @src do + * not meet and we need an extra run to fill the gap. + */ + marker = loc + ssize - left + disc; /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, magic, loc, dsize - loc); - ntfs_rl_mc(dst, loc + disc - hole, src, left, ssize - left); + ntfs_rl_mm(dst, marker, loc, dsize - loc); + ntfs_rl_mc(dst, loc + disc, src, left, ssize - left); - /* Adjust the VCN of the last run ... */ - if (dst[magic].lcn <= LCN_HOLE) - dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length; + /* Adjust the VCN of the first run after the insertion... */ + dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; /* ... and the length. */ - if (dst[magic].lcn == LCN_HOLE || dst[magic].lcn == LCN_RL_NOT_MAPPED) - dst[magic].length = dst[magic + 1].vcn - dst[magic].vcn; + if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED) + dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn; - /* Writing beyond the end of the file and there's a discontinuity. */ + /* Writing beyond the end of the file and there is a discontinuity. */ if (disc) { - if (hole) - dst[loc - 1].length = dst[loc].vcn - dst[loc - 1].vcn; - else { - if (loc > 0) { - dst[loc].vcn = dst[loc - 1].vcn + - dst[loc - 1].length; - dst[loc].length = dst[loc + 1].vcn - - dst[loc].vcn; - } else { - dst[loc].vcn = 0; - dst[loc].length = dst[loc + 1].vcn; - } - dst[loc].lcn = LCN_RL_NOT_MAPPED; + if (loc > 0) { + dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length; + dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; + } else { + dst[loc].vcn = 0; + dst[loc].length = dst[loc + 1].vcn; } - - magic += hole; - - if (dst[magic].lcn == LCN_ENOENT) - dst[magic].vcn = dst[magic - 1].vcn + - dst[magic - 1].length; + dst[loc].lcn = LCN_RL_NOT_MAPPED; } return dst; } @@ -385,9 +376,10 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst, static inline runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL left = FALSE; - BOOL right; - int magic; + BOOL left = FALSE; /* Left end of @src needs merging. */ + BOOL right; /* Right end of @src needs merging. */ + int tail; /* Start of tail of @dst. */ + int marker; /* End of the inserted runs. */ BUG_ON(!dst); BUG_ON(!src); @@ -396,9 +388,10 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); if (loc > 0) left = ntfs_are_rl_mergeable(dst + loc - 1, src); - - /* Allocate some space. We'll need less if the left, right, or both - * ends were merged. */ + /* + * Allocate some space. We will need less if the left, right, or both + * ends were merged. + */ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); if (IS_ERR(dst)) return dst; @@ -410,17 +403,28 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); if (left) __ntfs_rl_merge(dst + loc - 1, src); - - /* FIXME: What does this mean? (AIA) */ - magic = loc + ssize - left; + /* + * First run of @dst that needs to be moved out of the way to make + * space for the runs to be copied from @src, i.e. the first run of the + * tail of @dst. + */ + tail = loc + right + 1; + /* + * First run after the @src runs that have been inserted, i.e. where + * the tail of @dst needs to be moved to. + * Nominally, marker equals @loc + @ssize, i.e. location + number of + * runs in @src). However, if @left, then the first run in @src has + * been merged with one in @dst. + */ + marker = loc + ssize - left; /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, magic, loc + right + 1, dsize - loc - right - 1); + ntfs_rl_mm(dst, marker, tail, dsize - tail); ntfs_rl_mc(dst, loc, src, left, ssize - left); - /* We may have changed the length of the file, so fix the end marker */ - if (dst[magic].lcn == LCN_ENOENT) - dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length; + /* We may have changed the length of the file, so fix the end marker. */ + if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT) + dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; return dst; } -- cgit v0.10.2 From 4e64c88693fde1b1cbaa4cfecad43a0c3fad354e Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 19 Sep 2005 09:38:41 +0100 Subject: NTFS: Fix handling of compressed directories that I broke in earlier changeset. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index b6cc8cf..5fd516f 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -389,9 +389,11 @@ retry_readpage: * Only $DATA attributes can be encrypted and only unnamed $DATA * attributes can be compressed. Index root can have the flags set but * this means to create compressed/encrypted files, not that the - * attribute is compressed/encrypted. + * attribute is compressed/encrypted. Note we need to check for + * AT_INDEX_ALLOCATION since this is the type of both directory and + * index inodes. */ - if (ni->type != AT_INDEX_ROOT) { + if (ni->type != AT_INDEX_ALLOCATION) { /* If attribute is encrypted, deny access, just like NT4. */ if (NInoEncrypted(ni)) { BUG_ON(ni->type != AT_DATA); @@ -1341,9 +1343,11 @@ retry_writepage: * Only $DATA attributes can be encrypted and only unnamed $DATA * attributes can be compressed. Index root can have the flags set but * this means to create compressed/encrypted files, not that the - * attribute is compressed/encrypted. + * attribute is compressed/encrypted. Note we need to check for + * AT_INDEX_ALLOCATION since this is the type of both directory and + * index inodes. */ - if (ni->type != AT_INDEX_ROOT) { + if (ni->type != AT_INDEX_ALLOCATION) { /* If file is encrypted, deny access, just like NT4. */ if (NInoEncrypted(ni)) { unlock_page(page); -- cgit v0.10.2 From f6098cf449b81c14a51e48dd22ae47d03126a1de Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 19 Sep 2005 09:41:39 +0100 Subject: NTFS: Fix ntfs_{read,write}page() to cope with concurrent truncates better. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 5fd516f..5e80c07 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -59,39 +59,49 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) unsigned long flags; struct buffer_head *first, *tmp; struct page *page; + struct inode *vi; ntfs_inode *ni; int page_uptodate = 1; page = bh->b_page; - ni = NTFS_I(page->mapping->host); + vi = page->mapping->host; + ni = NTFS_I(vi); if (likely(uptodate)) { - s64 file_ofs, initialized_size; + loff_t i_size; + s64 file_ofs, init_size; set_buffer_uptodate(bh); file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); read_lock_irqsave(&ni->size_lock, flags); - initialized_size = ni->initialized_size; + init_size = ni->initialized_size; + i_size = i_size_read(vi); read_unlock_irqrestore(&ni->size_lock, flags); + if (unlikely(init_size > i_size)) { + /* Race with shrinking truncate. */ + init_size = i_size; + } /* Check for the current buffer head overflowing. */ - if (file_ofs + bh->b_size > initialized_size) { - char *addr; - int ofs = 0; - - if (file_ofs < initialized_size) - ofs = initialized_size - file_ofs; - addr = kmap_atomic(page, KM_BIO_SRC_IRQ); - memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs); + if (unlikely(file_ofs + bh->b_size > init_size)) { + u8 *kaddr; + int ofs; + + ofs = 0; + if (file_ofs < init_size) + ofs = init_size - file_ofs; + kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); + memset(kaddr + bh_offset(bh) + ofs, 0, + bh->b_size - ofs); + kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); flush_dcache_page(page); - kunmap_atomic(addr, KM_BIO_SRC_IRQ); } } else { clear_buffer_uptodate(bh); SetPageError(page); - ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.", - (unsigned long long)bh->b_blocknr); + ntfs_error(ni->vol->sb, "Buffer I/O error, logical block " + "0x%llx.", (unsigned long long)bh->b_blocknr); } first = page_buffers(page); local_irq_save(flags); @@ -124,7 +134,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) if (likely(page_uptodate && !PageError(page))) SetPageUptodate(page); } else { - char *addr; + u8 *kaddr; unsigned int i, recs; u32 rec_size; @@ -132,12 +142,12 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) recs = PAGE_CACHE_SIZE / rec_size; /* Should have been verified before we got here... */ BUG_ON(!recs); - addr = kmap_atomic(page, KM_BIO_SRC_IRQ); + kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); for (i = 0; i < recs; i++) - post_read_mst_fixup((NTFS_RECORD*)(addr + + post_read_mst_fixup((NTFS_RECORD*)(kaddr + i * rec_size), rec_size); + kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); flush_dcache_page(page); - kunmap_atomic(addr, KM_BIO_SRC_IRQ); if (likely(page_uptodate && !PageError(page))) SetPageUptodate(page); } @@ -168,8 +178,11 @@ still_busy: */ static int ntfs_read_block(struct page *page) { + loff_t i_size; VCN vcn; LCN lcn; + s64 init_size; + struct inode *vi; ntfs_inode *ni; ntfs_volume *vol; runlist_element *rl; @@ -180,7 +193,8 @@ static int ntfs_read_block(struct page *page) int i, nr; unsigned char blocksize_bits; - ni = NTFS_I(page->mapping->host); + vi = page->mapping->host; + ni = NTFS_I(vi); vol = ni->vol; /* $MFT/$DATA must have its complete runlist in memory at all times. */ @@ -199,11 +213,28 @@ static int ntfs_read_block(struct page *page) bh = head = page_buffers(page); BUG_ON(!bh); + /* + * We may be racing with truncate. To avoid some of the problems we + * now take a snapshot of the various sizes and use those for the whole + * of the function. In case of an extending truncate it just means we + * may leave some buffers unmapped which are now allocated. This is + * not a problem since these buffers will just get mapped when a write + * occurs. In case of a shrinking truncate, we will detect this later + * on due to the runlist being incomplete and if the page is being + * fully truncated, truncate will throw it away as soon as we unlock + * it so no need to worry what we do with it. + */ iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); read_lock_irqsave(&ni->size_lock, flags); lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; - zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits; + init_size = ni->initialized_size; + i_size = i_size_read(vi); read_unlock_irqrestore(&ni->size_lock, flags); + if (unlikely(init_size > i_size)) { + /* Race with shrinking truncate. */ + init_size = i_size; + } + zblock = (init_size + blocksize - 1) >> blocksize_bits; /* Loop through all the buffers in the page. */ rl = NULL; @@ -366,6 +397,8 @@ handle_zblock: */ static int ntfs_readpage(struct file *file, struct page *page) { + loff_t i_size; + struct inode *vi; ntfs_inode *ni, *base_ni; u8 *kaddr; ntfs_attr_search_ctx *ctx; @@ -384,7 +417,8 @@ retry_readpage: unlock_page(page); return 0; } - ni = NTFS_I(page->mapping->host); + vi = page->mapping->host; + ni = NTFS_I(vi); /* * Only $DATA attributes can be encrypted and only unnamed $DATA * attributes can be compressed. Index root can have the flags set but @@ -458,7 +492,12 @@ retry_readpage: read_lock_irqsave(&ni->size_lock, flags); if (unlikely(attr_len > ni->initialized_size)) attr_len = ni->initialized_size; + i_size = i_size_read(vi); read_unlock_irqrestore(&ni->size_lock, flags); + if (unlikely(attr_len > i_size)) { + /* Race with shrinking truncate. */ + attr_len = i_size; + } kaddr = kmap_atomic(page, KM_USER0); /* Copy the data to the page. */ memcpy(kaddr, (u8*)ctx->attr + @@ -1383,8 +1422,8 @@ retry_writepage: unsigned int ofs = i_size & ~PAGE_CACHE_MASK; kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs); - flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); + flush_dcache_page(page); } /* Handle mst protected attributes. */ if (NInoMstProtected(ni)) @@ -1447,34 +1486,33 @@ retry_writepage: BUG_ON(PageWriteback(page)); set_page_writeback(page); unlock_page(page); - /* - * Here, we do not need to zero the out of bounds area everytime - * because the below memcpy() already takes care of the - * mmap-at-end-of-file requirements. If the file is converted to a - * non-resident one, then the code path use is switched to the - * non-resident one where the zeroing happens on each ntfs_writepage() - * invocation. - */ attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); i_size = i_size_read(vi); if (unlikely(attr_len > i_size)) { + /* Race with shrinking truncate or a failed truncate. */ attr_len = i_size; - ctx->attr->data.resident.value_length = cpu_to_le32(attr_len); + /* + * If the truncate failed, fix it up now. If a concurrent + * truncate, we do its job, so it does not have to do anything. + */ + err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, + attr_len); + /* Shrinking cannot fail. */ + BUG_ON(err); } kaddr = kmap_atomic(page, KM_USER0); /* Copy the data from the page to the mft record. */ memcpy((u8*)ctx->attr + le16_to_cpu(ctx->attr->data.resident.value_offset), kaddr, attr_len); - flush_dcache_mft_record_page(ctx->ntfs_ino); /* Zero out of bounds area in the page cache page. */ memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); - flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); - + flush_dcache_mft_record_page(ctx->ntfs_ino); + flush_dcache_page(page); + /* We are done with the page. */ end_page_writeback(page); - - /* Mark the mft record dirty, so it gets written back. */ + /* Finally, mark the mft record dirty, so it gets written back. */ mark_mft_record_dirty(ctx->ntfs_ino); ntfs_attr_put_search_ctx(ctx); unmap_mft_record(base_ni); diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index dc4bbe3..7ec0451 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1166,6 +1166,8 @@ err_out: * * Return 0 on success and -errno on error. In the error case, the inode will * have had make_bad_inode() executed on it. + * + * Note this cannot be called for AT_INDEX_ALLOCATION. */ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) { @@ -1242,8 +1244,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) } } /* - * The encryption flag set in an index root just means to - * compress all files. + * The compressed/sparse flag set in an index root just means + * to compress all files. */ if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) { ntfs_error(vi->i_sb, "Found mst protected attribute " @@ -1319,8 +1321,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) "the mapping pairs array."); goto unm_err_out; } - if ((NInoCompressed(ni) || NInoSparse(ni)) && - ni->type != AT_INDEX_ROOT) { + if (NInoCompressed(ni) || NInoSparse(ni)) { if (a->data.non_resident.compression_unit != 4) { ntfs_error(vi->i_sb, "Found nonstandard " "compression unit (%u instead " diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h index 3288bcc..006946e 100644 --- a/fs/ntfs/malloc.h +++ b/fs/ntfs/malloc.h @@ -1,7 +1,7 @@ /* * malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published -- cgit v0.10.2 From 939647ee308e0ad924e776657704c7bedd498664 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 18 Sep 2005 15:05:20 -0500 Subject: [SCSI] fix oops on usb storage device disconnect We fix the oops by enforcing the host state model. There have also been two extra states added: SHOST_CANCEL_RECOVERY and SHOST_DEL_RECOVERY so we can take the model through host removal while the recovery thread is active. Signed-off-by: James Bottomley diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 85503fa..f2a72d3 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) switch (oldstate) { case SHOST_CREATED: case SHOST_RUNNING: + case SHOST_CANCEL_RECOVERY: break; default: goto illegal; @@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) case SHOST_DEL: switch (oldstate) { case SHOST_CANCEL: + case SHOST_DEL_RECOVERY: break; default: goto illegal; } break; + case SHOST_CANCEL_RECOVERY: + switch (oldstate) { + case SHOST_CANCEL: + case SHOST_RECOVERY: + break; + default: + goto illegal; + } + break; + + case SHOST_DEL_RECOVERY: + switch (oldstate) { + case SHOST_CANCEL_RECOVERY: + break; + default: + goto illegal; + } + break; } shost->shost_state = state; return 0; @@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state); **/ void scsi_remove_host(struct Scsi_Host *shost) { + unsigned long flags; down(&shost->scan_mutex); - scsi_host_set_state(shost, SHOST_CANCEL); + spin_lock_irqsave(shost->host_lock, flags); + if (scsi_host_set_state(shost, SHOST_CANCEL)) + if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { + spin_unlock_irqrestore(shost->host_lock, flags); + up(&shost->scan_mutex); + return; + } + spin_unlock_irqrestore(shost->host_lock, flags); up(&shost->scan_mutex); scsi_forget_host(shost); scsi_proc_host_rm(shost); - scsi_host_set_state(shost, SHOST_DEL); + spin_lock_irqsave(shost->host_lock, flags); + if (scsi_host_set_state(shost, SHOST_DEL)) + BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); + spin_unlock_irqrestore(shost->host_lock, flags); transport_unregister_device(&shost->shost_gendev); class_device_unregister(&shost->shost_classdev); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a780546..1f0ebab 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1265,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) list_for_each_safe(lh, lh_sf, &active_list) { scmd = list_entry(lh, struct scsi_cmnd, eh_entry); list_del_init(lh); - if (recovery) { - scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); - } else { + if (recovery && + !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) { scmd->result = (DID_ABORT << 16); scsi_finish_command(scmd); } diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 895c945..af589fa 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) { struct Scsi_Host *shost = scmd->device->host; unsigned long flags; + int ret = 0; if (shost->eh_wait == NULL) return 0; spin_lock_irqsave(shost->host_lock, flags); + if (scsi_host_set_state(shost, SHOST_RECOVERY)) + if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) + goto out_unlock; + ret = 1; scmd->eh_eflags |= eh_flag; list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); - scsi_host_set_state(shost, SHOST_RECOVERY); shost->host_failed++; scsi_eh_wakeup(shost); + out_unlock: spin_unlock_irqrestore(shost->host_lock, flags); - return 1; + return ret; } /** @@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd) } if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { - panic("Error handler thread not present at %p %p %s %d", - scmd, scmd->device->host, __FILE__, __LINE__); + scmd->result |= DID_TIME_OUT << 16; + __scsi_done(scmd); } } @@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) { int online; - wait_event(sdev->host->host_wait, (sdev->host->shost_state != - SHOST_RECOVERY)); + wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host)); online = scsi_device_online(sdev); @@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) static void scsi_restart_operations(struct Scsi_Host *shost) { struct scsi_device *sdev; + unsigned long flags; /* * If the door was locked, we need to insert a door lock request @@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost) SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", __FUNCTION__)); - scsi_host_set_state(shost, SHOST_RUNNING); + spin_lock_irqsave(shost->host_lock, flags); + if (scsi_host_set_state(shost, SHOST_RUNNING)) + if (scsi_host_set_state(shost, SHOST_CANCEL)) + BUG_ON(scsi_host_set_state(shost, SHOST_DEL)); + spin_unlock_irqrestore(shost->host_lock, flags); wake_up(&shost->host_wait); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index b7fddac..de7f98c 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, * error processing, as long as the device was opened * non-blocking */ if (filp && filp->f_flags & O_NONBLOCK) { - if (sdev->host->shost_state == SHOST_RECOVERY) + if (scsi_host_in_recovery(sdev->host)) return -ENODEV; } else if (!scsi_block_when_processing_errors(sdev)) return -ENODEV; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f065cbc..dc9c772 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -447,7 +447,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) spin_lock_irqsave(shost->host_lock, flags); shost->host_busy--; - if (unlikely((shost->shost_state == SHOST_RECOVERY) && + if (unlikely(scsi_host_in_recovery(shost) && shost->host_failed)) scsi_eh_wakeup(shost); spin_unlock(shost->host_lock); @@ -1339,7 +1339,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, struct scsi_device *sdev) { - if (shost->shost_state == SHOST_RECOVERY) + if (scsi_host_in_recovery(shost)) return 0; if (shost->host_busy == 0 && shost->host_blocked) { /* diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 1e47b7e..72a6550 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -57,6 +57,8 @@ static struct { { SHOST_CANCEL, "cancel" }, { SHOST_DEL, "deleted" }, { SHOST_RECOVERY, "recovery" }, + { SHOST_CANCEL_RECOVERY, "cancel/recovery" }, + { SHOST_DEL_RECOVERY, "deleted/recovery", }, }; const char *scsi_host_state_name(enum scsi_host_state state) { diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9ea4765..4d09a6e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if (sdp->detached) return -ENODEV; if (filp->f_flags & O_NONBLOCK) { - if (sdp->device->host->shost_state == SHOST_RECOVERY) + if (scsi_host_in_recovery(sdp->device->host)) return -EBUSY; } else if (!scsi_block_when_processing_errors(sdp->device)) return -EBUSY; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 916144b..540369f 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -439,6 +439,8 @@ enum scsi_host_state { SHOST_CANCEL, SHOST_DEL, SHOST_RECOVERY, + SHOST_CANCEL_RECOVERY, + SHOST_DEL_RECOVERY, }; struct Scsi_Host { @@ -621,6 +623,13 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev) return container_of(dev, struct Scsi_Host, shost_gendev); } +static inline int scsi_host_in_recovery(struct Scsi_Host *shost) +{ + return shost->shost_state == SHOST_RECOVERY || + shost->shost_state == SHOST_CANCEL_RECOVERY || + shost->shost_state == SHOST_DEL_RECOVERY; +} + extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); extern void scsi_flush_work(struct Scsi_Host *); -- cgit v0.10.2 From 3ed7a4704beb66a155acd67b78b7e9a5674d55fb Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 19 Sep 2005 09:50:04 -0500 Subject: [SCSI] Fix thread termination for the SCSI error handle From: Alan Stern This patch (as561) fixes the error handler's thread-exit code. The kthread_stop call won't wake the thread from a down_interruptible, so the patch gets rid of the semaphore and simply does set_current_state(TASK_INTERRUPTIBLE); Signed-off-by: Alan Stern Modified to simplify the termination loop and correct the sleep condition. Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index af589fa..ad53421 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -50,7 +50,7 @@ void scsi_eh_wakeup(struct Scsi_Host *shost) { if (shost->host_busy == shost->host_failed) { - up(shost->eh_wait); + wake_up_process(shost->ehandler); SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread\n")); } @@ -70,7 +70,7 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) unsigned long flags; int ret = 0; - if (shost->eh_wait == NULL) + if (!shost->ehandler) return 0; spin_lock_irqsave(shost->host_lock, flags); @@ -1591,40 +1591,31 @@ int scsi_error_handler(void *data) { struct Scsi_Host *shost = (struct Scsi_Host *) data; int rtn; - DECLARE_MUTEX_LOCKED(sem); current->flags |= PF_NOFREEZE; - shost->eh_wait = &sem; + /* - * Wake up the thread that created us. + * Note - we always use TASK_INTERRUPTIBLE even if the module + * was loaded as part of the kernel. The reason is that + * UNINTERRUPTIBLE would cause this thread to be counted in + * the load average as a running process, and an interruptible + * wait doesn't. */ - SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" - " scsi_eh_%d\n",shost->host_no)); - - while (1) { - /* - * If we get a signal, it means we are supposed to go - * away and die. This typically happens if the user is - * trying to unload a module. - */ - SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" - " scsi_eh_%d" - " sleeping\n",shost->host_no)); - - /* - * Note - we always use down_interruptible with the semaphore - * even if the module was loaded as part of the kernel. The - * reason is that down() will cause this thread to be counted - * in the load average as a running process, and down - * interruptible doesn't. Given that we need to allow this - * thread to die if the driver was loaded as a module, using - * semaphores isn't unreasonable. - */ - down_interruptible(&sem); - if (kthread_should_stop()) - break; + set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + if (shost->host_failed == 0 || + shost->host_failed != shost->host_busy) { + SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" + " scsi_eh_%d" + " sleeping\n", + shost->host_no)); + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + continue; + } + __set_current_state(TASK_RUNNING); SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" " scsi_eh_%d waking" " up\n",shost->host_no)); @@ -1651,7 +1642,7 @@ int scsi_error_handler(void *data) * which are still online. */ scsi_restart_operations(shost); - + set_current_state(TASK_INTERRUPTIBLE); } SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" @@ -1660,7 +1651,7 @@ int scsi_error_handler(void *data) /* * Make sure that nobody tries to wake us up again. */ - shost->eh_wait = NULL; + shost->ehandler = NULL; return 0; } diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 540369f..69313ba 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -467,8 +467,6 @@ struct Scsi_Host { struct list_head eh_cmd_q; struct task_struct * ehandler; /* Error recovery thread. */ - struct semaphore * eh_wait; /* The error recovery thread waits - on this. */ struct semaphore * eh_action; /* Wait for specific actions on the host. */ unsigned int eh_active:1; /* Indicates the eh thread is awake and active if -- cgit v0.10.2 From 6577ae51cf52f5fb0e4a85e673dd7bf2d0074e3e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 19 Sep 2005 09:17:56 -0700 Subject: [PATCH] IB/mthca: Don't try to set srq->last for userspace SRQs Userspace SRQs don't have a buffer allocated for them in the kernel, so it doesn't make sense to set srq->last during initialization. In fact, this can crash trying to follow a nonexistent buffer pointer. Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 45dedd2..18998d4 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -172,6 +172,8 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd, scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY); } + srq->last = get_wqe(srq, srq->max - 1); + return 0; } @@ -263,7 +265,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, srq->first_free = 0; srq->last_free = srq->max - 1; - srq->last = get_wqe(srq, srq->max - 1); return 0; -- cgit v0.10.2 From 997a51ae373df6484cdd4a5fc61a9c9bec82cd68 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Mon, 19 Sep 2005 18:55:51 +0400 Subject: [PATCH] Alpha: ISA IRQs fixup for dp264 Basically, this extends original dp264 fixup to all dp264 variations. Here is one minor change: mask out bits 4-7 of a value assigned by SRM, because - newer consoles report ISA IRQs with offset 0xe0; - even if console IRQ value is bogus, we'll have a value < 16 so it should be harmless as it won't clash with native IRQs. Particularly this fixes USB interrupt problem on xp1000 and es40. Signed-off-by: Ivan Kokshaysky Acked-by: Richard Henderson Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 9e36b07..d5da6b1 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c @@ -395,6 +395,22 @@ clipper_init_irq(void) */ static int __init +isa_irq_fixup(struct pci_dev *dev, int irq) +{ + u8 irq8; + + if (irq > 0) + return irq; + + /* This interrupt is routed via ISA bridge, so we'll + just have to trust whatever value the console might + have assigned. */ + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8); + + return irq8 & 0xf; +} + +static int __init dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { static char irq_tab[6][5] __initdata = { @@ -407,25 +423,13 @@ dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */ }; const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; - struct pci_controller *hose = dev->sysdata; int irq = COMMON_TABLE_LOOKUP; - if (irq > 0) { + if (irq > 0) irq += 16 * hose->index; - } else { - /* ??? The Contaq IDE controller on the ISA bridge uses - "legacy" interrupts 14 and 15. I don't know if anything - can wind up at the same slot+pin on hose1, so we'll - just have to trust whatever value the console might - have assigned. */ - - u8 irq8; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8); - irq = irq8; - } - return irq; + return isa_irq_fixup(dev, irq); } static int __init @@ -453,7 +457,8 @@ monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { 24, 24, 25, 26, 27} /* IdSel 15 slot 5 PCI2*/ }; const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5; - return COMMON_TABLE_LOOKUP; + + return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP); } static u8 __init @@ -507,7 +512,8 @@ webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */ }; const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5; - return COMMON_TABLE_LOOKUP; + + return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP); } static int __init @@ -524,14 +530,13 @@ clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */ }; const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5; - struct pci_controller *hose = dev->sysdata; int irq = COMMON_TABLE_LOOKUP; if (irq > 0) irq += 16 * hose->index; - return irq; + return isa_irq_fixup(dev, irq); } static void __init -- cgit v0.10.2 From 82ffb67164064752a56669511545316075b41e1d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Sep 2005 16:25:54 +0200 Subject: [SCSI] fusion core changes for SAS support - various bits for SAS support from the LSI driver. - use the device private data for the fusion target private data. this should be using the midlayer target data framework, but we can't move over to that until fusion has been switched to the generic DV code - use target ID and channel from the fusion target private data, because those in scsi_device will be different for mptsas Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index f517d06..14d62d9 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -141,7 +141,7 @@ static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); -static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag); +static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); @@ -152,6 +152,7 @@ static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); static int GetLanConfigPages(MPT_ADAPTER *ioc); static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); static int GetIoUnitPage2(MPT_ADAPTER *ioc); +int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); @@ -159,6 +160,8 @@ static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); static void mpt_timer_expired(unsigned long data); static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); +static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); +static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); #ifdef CONFIG_PROC_FS static int procmpt_summary_read(char *buf, char **start, off_t offset, @@ -509,6 +512,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) pCfg->wait_done = 1; wake_up(&mpt_waitq); } + } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { + /* we should be always getting a reply frame */ + memcpy(ioc->persist_reply_frame, reply, + min(MPT_DEFAULT_FRAME_SIZE, + 4*reply->u.reply.MsgLength)); + del_timer(&ioc->persist_timer); + ioc->persist_wait_done = 1; + wake_up(&mpt_waitq); } else { printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", ioc->name, func); @@ -750,6 +761,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, u.frame.linkage.list); list_del(&mf->u.frame.linkage.list); + mf->u.frame.linkage.arg1 = 0; mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ @@ -845,6 +857,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); + mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); #ifdef MFCNT ioc->mfcnt--; @@ -971,12 +984,123 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); - + return r; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** + * mpt_host_page_access_control - provides mechanism for the host + * driver to control the IOC's Host Page Buffer access. + * @ioc: Pointer to MPT adapter structure + * @access_control_value: define bits below + * + * Access Control Value - bits[15:12] + * 0h Reserved + * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } + * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } + * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } + * + * Returns 0 for success, non-zero for failure. + */ + +static int +mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) +{ + int r = 0; + + /* return if in use */ + if (CHIPREG_READ32(&ioc->chip->Doorbell) + & MPI_DOORBELL_ACTIVE) + return -1; + + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + + CHIPREG_WRITE32(&ioc->chip->Doorbell, + ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL + <HostPageBuffer) { + + host_page_buffer_sz = + le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF; + + if(!host_page_buffer_sz) + return 0; /* fw doesn't need any host buffers */ + + /* spin till we get enough memory */ + while(host_page_buffer_sz > 0) { + + if((ioc->HostPageBuffer = pci_alloc_consistent( + ioc->pcidev, + host_page_buffer_sz, + &ioc->HostPageBuffer_dma)) != NULL) { + + dinitprintk((MYIOC_s_INFO_FMT + "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", + ioc->name, + ioc->HostPageBuffer, + ioc->HostPageBuffer_dma, + hst_page_buffer_sz)); + ioc->alloc_total += host_page_buffer_sz; + ioc->HostPageBuffer_sz = host_page_buffer_sz; + break; + } + + host_page_buffer_sz -= (4*1024); + } + } + + if(!ioc->HostPageBuffer) { + printk(MYIOC_s_ERR_FMT + "Failed to alloc memory for host_page_buffer!\n", + ioc->name); + return -999; + } + + psge = (char *)&ioc_init->HostPageBufferSGE; + flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT | + MPI_SGE_FLAGS_SYSTEM_ADDRESS | + MPI_SGE_FLAGS_32_BIT_ADDRESSING | + MPI_SGE_FLAGS_HOST_TO_IOC | + MPI_SGE_FLAGS_END_OF_BUFFER; + if (sizeof(dma_addr_t) == sizeof(u64)) { + flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; + } + flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; + flags_length |= ioc->HostPageBuffer_sz; + mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); + ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; + +return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/** * mpt_verify_adapter - Given a unique IOC identifier, set pointer to * the associated MPT adapter structure. * @iocid: IOC unique identifier (integer) @@ -1213,6 +1337,33 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->prod_name = "LSI53C1035"; ioc->bus_type = SCSI; } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { + ioc->prod_name = "LSISAS1064"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) { + ioc->prod_name = "LSISAS1066"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { + ioc->prod_name = "LSISAS1068"; + ioc->bus_type = SAS; + ioc->errata_flag_1064 = 1; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { + ioc->prod_name = "LSISAS1064E"; + ioc->bus_type = SAS; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) { + ioc->prod_name = "LSISAS1066E"; + ioc->bus_type = SAS; + } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { + ioc->prod_name = "LSISAS1068E"; + ioc->bus_type = SAS; + } if (ioc->errata_flag_1064) pci_disable_io_access(pdev); @@ -1640,7 +1791,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * and we try GetLanConfigPages again... */ if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { - if (ioc->bus_type == FC) { + if (ioc->bus_type == SAS) { + + /* clear persistency table */ + if(ioc->facts.IOCExceptions & + MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { + ret = mptbase_sas_persist_operation(ioc, + MPI_SAS_OP_CLEAR_NOT_PRESENT); + if(ret != 0) + return -1; + } + + /* Find IM volumes + */ + mpt_findImVolumes(ioc); + + } else if (ioc->bus_type == FC) { /* * Pre-fetch FC port WWN and stuff... * (FCPortPage0_t stuff) @@ -1783,7 +1949,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->cached_fw != NULL) { ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); - if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) { + if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", ret); } @@ -1852,6 +2018,23 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) kfree(ioc->ChainToChain); ioc->ChainToChain = NULL; + + if (ioc->HostPageBuffer != NULL) { + if((ret = mpt_host_page_access_control(ioc, + MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { + printk(KERN_ERR MYNAM + ": %s: host page buffers free failed (%d)!\n", + __FUNCTION__, ret); + } + dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", + ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); + pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, + ioc->HostPageBuffer, + ioc->HostPageBuffer_dma); + ioc->HostPageBuffer = NULL; + ioc->HostPageBuffer_sz = 0; + ioc->alloc_total -= ioc->HostPageBuffer_sz; + } } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2034,7 +2217,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Loop here waiting for IOC to come READY. */ ii = 0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */ + cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */ while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { @@ -2212,6 +2395,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) le32_to_cpu(facts->CurrentSenseBufferHighAddr); facts->CurReplyFrameSize = le16_to_cpu(facts->CurReplyFrameSize); + facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities); /* * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx @@ -2383,13 +2567,25 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", ioc->name, ioc->upload_fw, ioc->facts.Flags)); - if (ioc->bus_type == FC) + if(ioc->bus_type == SAS) + ioc_init.MaxDevices = ioc->facts.MaxDevices; + else if(ioc->bus_type == FC) ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; else ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; - ioc_init.MaxBuses = MPT_MAX_BUS; - + dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", + ioc->name, ioc->facts.MsgVersion)); + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { + // set MsgVersion and HeaderVersion host driver was built with + ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION); + ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION); + + if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) { + ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE; + } else if(mpt_host_page_alloc(ioc, &ioc_init)) + return -99; + } ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ if (sizeof(dma_addr_t) == sizeof(u64)) { @@ -2403,17 +2599,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) ioc_init.HostMfaHighAddr = cpu_to_le32(0); ioc_init.SenseBufferHighAddr = cpu_to_le32(0); } - + ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; + ioc->facts.MaxDevices = ioc_init.MaxDevices; + ioc->facts.MaxBuses = ioc_init.MaxBuses; dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", ioc->name, &ioc_init)); r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); - if (r != 0) + if (r != 0) { + printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r); return r; + } /* No need to byte swap the multibyte fields in the reply * since we don't even look at it's contents. @@ -2472,7 +2672,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) { PortEnable_t port_enable; MPIDefaultReply_t reply_buf; - int ii; + int rc; int req_sz; int reply_sz; @@ -2494,22 +2694,15 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* RAID FW may take a long time to enable */ - if (ioc->bus_type == FC) { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, - reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); - } else { - ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, + if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) + > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); + } else { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, + reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); } - - if (ii != 0) - return ii; - - /* We do not even look at the reply, so we need not - * swap the multi-byte fields. - */ - - return 0; + return rc; } /* @@ -2666,9 +2859,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) * <0 for fw upload failure. */ static int -mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) +mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) { - MpiFwHeader_t *pFwHeader; MpiExtImageHeader_t *pExtImage; u32 fwSize; u32 diag0val; @@ -2679,18 +2871,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) u32 load_addr; u32 ioc_state=0; - ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", - ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); - - if ( ioc->facts.FWImageSize == 0 ) - return -1; - - if (ioc->cached_fw == NULL) - return -2; - - /* prevent a second downloadboot and memory free with alt_ioc */ - if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) - ioc->alt_ioc->cached_fw = NULL; + ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", + ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); @@ -2718,16 +2900,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) ioc->name, count)); break; } - /* wait 1 sec */ + /* wait .1 sec */ if (sleepFlag == CAN_SLEEP) { - msleep_interruptible (1000); + msleep_interruptible (100); } else { - mdelay (1000); + mdelay (100); } } if ( count == 30 ) { - ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! " + "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", ioc->name, diag0val)); return -3; } @@ -2742,7 +2925,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Set the DiagRwEn and Disable ARM bits */ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); - pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; fwSize = (pFwHeader->ImageSize + 3)/4; ptrFw = (u32 *) pFwHeader; @@ -2792,19 +2974,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Clear the internal flash bad bit - autoincrementing register, * so must do two writes. */ - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); - diagRwData |= 0x4000000; - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); - CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + if (ioc->bus_type == SCSI) { + /* + * 1030 and 1035 H/W errata, workaround to access + * the ClearFlashBadSignatureBit + */ + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); + diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); + diagRwData |= 0x40000000; + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + + } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ { + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | + MPI_DIAG_CLEAR_FLASH_BAD_SIG); + + /* wait 1 msec */ + if (sleepFlag == CAN_SLEEP) { + msleep_interruptible (1); + } else { + mdelay (1); + } + } if (ioc->errata_flag_1064) pci_disable_io_access(ioc->pcidev); diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); - ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", + ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, " + "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", ioc->name, diag0val)); - diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); + diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", ioc->name, diag0val)); CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); @@ -2812,10 +3013,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) /* Write 0xFF to reset the sequencer */ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + if (ioc->bus_type == SAS) { + ioc_state = mpt_GetIocState(ioc, 0); + if ( (GetIocFacts(ioc, sleepFlag, + MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { + ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n", + ioc->name, ioc_state)); + return -EFAULT; + } + } + for (count=0; countname, count, ioc_state)); + if (ioc->bus_type == SAS) { + return 0; + } if ((SendIocInit(ioc, sleepFlag)) != 0) { ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", ioc->name)); @@ -3049,12 +3263,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) /* wait 1 sec */ if (sleepFlag == CAN_SLEEP) { - ssleep(1); + msleep_interruptible (1000); } else { mdelay (1000); } } - if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) { + if ((count = mpt_downloadboot(ioc, + (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) { printk(KERN_WARNING MYNAM ": firmware downloadboot failure (%d)!\n", count); } @@ -4001,6 +4216,85 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table + * @ioc: Pointer to MPT_ADAPTER structure + * @sas_address: 64bit SAS Address for operation. + * @target_id: specified target for operation + * @bus: specified bus for operation + * @persist_opcode: see below + * + * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for + * devices not currently present. + * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings + * + * NOTE: Don't use not this function during interrupt time. + * + * Returns: 0 for success, non-zero error + */ + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +int +mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) +{ + SasIoUnitControlRequest_t *sasIoUnitCntrReq; + SasIoUnitControlReply_t *sasIoUnitCntrReply; + MPT_FRAME_HDR *mf = NULL; + MPIHeader_t *mpi_hdr; + + + /* insure garbage is not sent to fw */ + switch(persist_opcode) { + + case MPI_SAS_OP_CLEAR_NOT_PRESENT: + case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: + break; + + default: + return -1; + break; + } + + printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode); + + /* Get a MF for this command. + */ + if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { + printk("%s: no msg frames!\n",__FUNCTION__); + return -1; + } + + mpi_hdr = (MPIHeader_t *) mf; + sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; + memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); + sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; + sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; + sasIoUnitCntrReq->Operation = persist_opcode; + + init_timer(&ioc->persist_timer); + ioc->persist_timer.data = (unsigned long) ioc; + ioc->persist_timer.function = mpt_timer_expired; + ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */; + ioc->persist_wait_done=0; + add_timer(&ioc->persist_timer); + mpt_put_msg_frame(mpt_base_index, ioc, mf); + wait_event(mpt_waitq, ioc->persist_wait_done); + + sasIoUnitCntrReply = + (SasIoUnitControlReply_t *)ioc->persist_reply_frame; + if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { + printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", + __FUNCTION__, + sasIoUnitCntrReply->IOCStatus, + sasIoUnitCntrReply->IOCLogInfo); + return -1; + } + + printk("%s: success\n",__FUNCTION__); + return 0; +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure * @@ -5366,8 +5660,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static char * -EventDescriptionStr(u8 event, u32 evData0) +static void +EventDescriptionStr(u8 event, u32 evData0, char *evStr) { char *ds; @@ -5420,8 +5714,95 @@ EventDescriptionStr(u8 event, u32 evData0) ds = "Events(OFF) Change"; break; case MPI_EVENT_INTEGRATED_RAID: - ds = "Integrated Raid"; + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_RAID_RC_VOLUME_CREATED : + ds = "Integrated Raid: Volume Created"; + break; + case MPI_EVENT_RAID_RC_VOLUME_DELETED : + ds = "Integrated Raid: Volume Deleted"; + break; + case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED : + ds = "Integrated Raid: Volume Settings Changed"; + break; + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED : + ds = "Integrated Raid: Volume Status Changed"; + break; + case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED : + ds = "Integrated Raid: Volume Physdisk Changed"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED : + ds = "Integrated Raid: Physdisk Created"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED : + ds = "Integrated Raid: Physdisk Deleted"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED : + ds = "Integrated Raid: Physdisk Settings Changed"; + break; + case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED : + ds = "Integrated Raid: Physdisk Status Changed"; + break; + case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED : + ds = "Integrated Raid: Domain Validation Needed"; + break; + case MPI_EVENT_RAID_RC_SMART_DATA : + ds = "Integrated Raid; Smart Data"; + break; + case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED : + ds = "Integrated Raid: Replace Action Started"; + break; + default: + ds = "Integrated Raid"; break; + } + break; + } + case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: + ds = "SCSI Device Status Change"; + break; + case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + ds = "SAS Device Status Change: Added"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + ds = "SAS Device Status Change: Deleted"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + ds = "SAS Device Status Change: SMART Data"; + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + ds = "SAS Device Status Change: No Persistancy Added"; + break; + default: + ds = "SAS Device Status Change: Unknown"; + break; + } + break; + } + case MPI_EVENT_ON_BUS_TIMER_EXPIRED: + ds = "Bus Timer Expired"; + break; + case MPI_EVENT_QUEUE_FULL: + ds = "Queue Full"; + break; + case MPI_EVENT_SAS_SES: + ds = "SAS SES Event"; + break; + case MPI_EVENT_PERSISTENT_TABLE_FULL: + ds = "Persistent Table Full"; + break; + case MPI_EVENT_SAS_PHY_LINK_STATUS: + ds = "SAS PHY Link Status"; + break; + case MPI_EVENT_SAS_DISCOVERY_ERROR: + ds = "SAS Discovery Error"; + break; + /* * MPT base "custom" events may be added here... */ @@ -5429,7 +5810,7 @@ EventDescriptionStr(u8 event, u32 evData0) ds = "Unknown"; break; } - return ds; + strcpy(evStr,ds); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -5451,7 +5832,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply int ii; int r = 0; int handlers = 0; - char *evStr; + char evStr[100]; u8 event; /* @@ -5464,7 +5845,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply evData0 = le32_to_cpu(pEventReply->Data[0]); } - evStr = EventDescriptionStr(event, evData0); + EventDescriptionStr(event, evData0, evStr); devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", ioc->name, evStr, @@ -5481,20 +5862,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * Do general / base driver event processing */ switch(event) { - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_UNIT_ATTENTION: /* 03 */ - case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - case MPI_EVENT_RESCAN: /* 06 */ - case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ - case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ - case MPI_EVENT_LOGOUT: /* 09 */ - case MPI_EVENT_INTEGRATED_RAID: /* 0B */ - case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */ - default: - break; case MPI_EVENT_EVENT_CHANGE: /* 0A */ if (evDataLen) { u8 evState = evData0 & 0xFF; @@ -5507,6 +5874,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } } break; + default: + break; } /* @@ -5814,6 +6183,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); EXPORT_SYMBOL(mpt_read_ioc_pg_3); EXPORT_SYMBOL(mpt_alloc_fw_memory); EXPORT_SYMBOL(mpt_free_fw_memory); +EXPORT_SYMBOL(mptbase_sas_persist_operation); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f4827d9..bbd21d7 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -65,6 +65,7 @@ #include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ #include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ #include "lsi/mpi_tool.h" /* Tools support */ +#include "lsi/mpi_sas.h" /* SAS support */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -477,6 +478,14 @@ typedef struct _ScsiCfgData { u8 rsvd[1]; } ScsiCfgData; +typedef struct _SasCfgData { + u8 ptClear; /* 1 to automatically clear the + * persistent table. + * 0 to disable + * automatic clearing. + */ +}SasCfgData; + /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS */ @@ -530,11 +539,15 @@ typedef struct _MPT_ADAPTER u8 *sense_buf_pool; dma_addr_t sense_buf_pool_dma; u32 sense_buf_low_dma; + u8 *HostPageBuffer; /* SAS - host page buffer support */ + u32 HostPageBuffer_sz; + dma_addr_t HostPageBuffer_dma; int mtrr_reg; struct pci_dev *pcidev; /* struct pci_dev pointer */ u8 __iomem *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */ ScsiCfgData spi_data; /* Scsi config. data */ + SasCfgData sas_data; /* Sas config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ @@ -554,31 +567,35 @@ typedef struct _MPT_ADAPTER #else u32 mfcnt; #endif - u32 NB_for_64_byte_frame; + u32 NB_for_64_byte_frame; u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; IOCFactsReply_t facts; PortFactsReply_t pfacts[2]; FCPortPage0_t fc_port_page0[2]; + struct timer_list persist_timer; /* persist table timer */ + int persist_wait_done; /* persist completion flag */ + u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ LANPage0_t lan_cnfg_page0; LANPage1_t lan_cnfg_page1; - /* + /* * Description: errata_flag_1064 * If a PCIX read occurs within 1 or 2 cycles after the chip receives * a split completion for a read data, an internal address pointer incorrectly * increments by 32 bytes */ - int errata_flag_1064; + int errata_flag_1064; u8 FirstWhoInit; u8 upload_fw; /* If set, do a fw upload */ u8 reload_fw; /* Force a FW Reload on next reset */ - u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ + u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ u8 pad1[4]; int DoneCtx; int TaskCtx; int InternalCtx; - struct list_head list; + struct list_head list; struct net_device *netdev; + struct list_head sas_topology; } MPT_ADAPTER; /* @@ -964,6 +981,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); extern int mpt_findImVolumes(MPT_ADAPTER *ioc); extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); +extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); /* * Public data decl's... diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4a003dc..58b5fde 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1256,8 +1256,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; - VirtDevice *pTarget; - int target; + VirtDevice *pTarget = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; @@ -1267,12 +1266,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) int ii; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; - target = SCpnt->device->id; lun = SCpnt->device->lun; SCpnt->scsi_done = done; - pTarget = hd->Targets[target]; - dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); @@ -1315,7 +1311,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ - if ( pTarget + if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; @@ -1325,8 +1321,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) target; - pScsiReq->Bus = (u8) SCpnt->device->channel; + pScsiReq->TargetID = (u8) pTarget->target_id; + pScsiReq->Bus = pTarget->bus_id; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len; @@ -1378,7 +1374,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION if (hd->ioc->bus_type == SCSI) { - int dvStatus = hd->ioc->spi_data.dvStatus[target]; + int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id]; int issueCmd = 1; if (dvStatus || hd->ioc->spi_data.forceDv) { @@ -2180,6 +2176,7 @@ mptscsih_slave_alloc(struct scsi_device *device) out: vdev->num_luns++; + device->hostdata = vdev; return 0; } -- cgit v0.10.2 From 0c33b27deb93178f10778b3d2669af1674793cef Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 9 Sep 2005 16:27:19 +0200 Subject: [SCSI] fusion SAS support (mptsas driver) Adds the actual mptsas driver, based upon the LSI driver with new work for SAS transport class integration from Eric Moore and me. This obviously depends on the SAS transport class. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 33f209a..1883d22 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -35,6 +35,23 @@ config FUSION_FC LSIFC929X LSIFC929XL +config FUSION_SAS + tristate "Fusion MPT ScsiHost drivers for SAS" + depends on PCI && SCSI + select FUSION + select SCSI_SAS_ATTRS + ---help--- + SCSI HOST support for a SAS host adapters. + + List of supported controllers: + + LSISAS1064 + LSISAS1066 + LSISAS1068 + LSISAS1064E + LSISAS1066E + LSISAS1068E + config FUSION_MAX_SGE int "Maximum number of scatter gather entries (16 - 128)" depends on FUSION diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 1d2f9db..8a2e265 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -34,5 +34,6 @@ obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o +obj-$(CONFIG_FUSION_SAS) += mptbase.o mptscsih.o mptsas.o obj-$(CONFIG_FUSION_CTL) += mptctl.o obj-$(CONFIG_FUSION_LAN) += mptlan.o diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c new file mode 100644 index 0000000..0d9a192 --- /dev/null +++ b/drivers/message/fusion/mptsas.c @@ -0,0 +1,1235 @@ +/* + * linux/drivers/message/fusion/mptsas.c + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2005 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsil.com) + * Copyright (c) 2005 Dell + */ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + 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; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + NO WARRANTY + THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is + solely responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, damage to or loss of data, + programs or equipment, and unavailability or interruption of operations. + + DISCLAIMER OF LIABILITY + NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mptbase.h" +#include "mptscsih.h" + + +#define my_NAME "Fusion MPT SAS Host driver" +#define my_VERSION MPT_LINUX_VERSION_COMMON +#define MYNAM "mptsas" + +MODULE_AUTHOR(MODULEAUTHOR); +MODULE_DESCRIPTION(my_NAME); +MODULE_LICENSE("GPL"); + +static int mpt_pq_filter; +module_param(mpt_pq_filter, int, 0); +MODULE_PARM_DESC(mpt_pq_filter, + "Enable peripheral qualifier filter: enable=1 " + "(default=0)"); + +static int mpt_pt_clear; +module_param(mpt_pt_clear, int, 0); +MODULE_PARM_DESC(mpt_pt_clear, + "Clear persistency table: enable=1 " + "(default=MPTSCSIH_PT_CLEAR=0)"); + +static int mptsasDoneCtx = -1; +static int mptsasTaskCtx = -1; +static int mptsasInternalCtx = -1; /* Used only for internal commands */ + + +/* + * SAS topology structures + * + * The MPT Fusion firmware interface spreads information about the + * SAS topology over many manufacture pages, thus we need some data + * structure to collect it and process it for the SAS transport class. + */ + +struct mptsas_devinfo { + u16 handle; /* unique id to address this device */ + u8 phy_id; /* phy number of parent device */ + u8 port_id; /* sas physical port this device + is assoc'd with */ + u8 target; /* logical target id of this device */ + u8 bus; /* logical bus number of this device */ + u64 sas_address; /* WWN of this device, + SATA is assigned by HBA,expander */ + u32 device_info; /* bitfield detailed info about this device */ +}; + +struct mptsas_phyinfo { + u8 phy_id; /* phy index */ + u8 port_id; /* port number this phy is part of */ + u8 negotiated_link_rate; /* nego'd link rate for this phy */ + u8 hw_link_rate; /* hardware max/min phys link rate */ + u8 programmed_link_rate; /* programmed max/min phy link rate */ + struct mptsas_devinfo identify; /* point to phy device info */ + struct mptsas_devinfo attached; /* point to attached device info */ + struct sas_rphy *rphy; +}; + +struct mptsas_portinfo { + struct list_head list; + u16 handle; /* unique id to address this */ + u8 num_phys; /* number of phys */ + struct mptsas_phyinfo *phy_info; +}; + +/* + * This is pretty ugly. We will be able to seriously clean it up + * once the DV code in mptscsih goes away and we can properly + * implement ->target_alloc. + */ +static int +mptsas_slave_alloc(struct scsi_device *device) +{ + struct Scsi_Host *host = device->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + struct sas_rphy *rphy; + struct mptsas_portinfo *p; + VirtDevice *vdev; + uint target = device->id; + int i; + + if ((vdev = hd->Targets[target]) != NULL) + goto out; + + vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", + hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + + memset(vdev, 0, sizeof(VirtDevice)); + vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; + vdev->ioc_id = hd->ioc->id; + + rphy = dev_to_rphy(device->sdev_target->dev.parent); + list_for_each_entry(p, &hd->ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + vdev->target_id = + p->phy_info[i].attached.target; + vdev->bus_id = p->phy_info[i].attached.bus; + hd->Targets[device->id] = vdev; + goto out; + } + } + } + + printk("No matching SAS device found!!\n"); + kfree(vdev); + return -ENODEV; + + out: + vdev->num_luns++; + device->hostdata = vdev; + return 0; +} + +static struct scsi_host_template mptsas_driver_template = { + .proc_name = "mptsas", + .proc_info = mptscsih_proc_info, + .name = "MPT SPI Host", + .info = mptscsih_info, + .queuecommand = mptscsih_qcmd, + .slave_alloc = mptsas_slave_alloc, + .slave_configure = mptscsih_slave_configure, + .slave_destroy = mptscsih_slave_destroy, + .change_queue_depth = mptscsih_change_queue_depth, + .eh_abort_handler = mptscsih_abort, + .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_FC_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, +}; + +static struct sas_function_template mptsas_transport_functions = { +}; + +static struct scsi_transport_template *mptsas_transport_template; + +#ifdef SASDEBUG +static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) +{ + printk("---- IO UNIT PAGE 0 ------------\n"); + printk("Handle=0x%X\n", + le16_to_cpu(phy_data->AttachedDeviceHandle)); + printk("Controller Handle=0x%X\n", + le16_to_cpu(phy_data->ControllerDevHandle)); + printk("Port=0x%X\n", phy_data->Port); + printk("Port Flags=0x%X\n", phy_data->PortFlags); + printk("PHY Flags=0x%X\n", phy_data->PhyFlags); + printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate); + printk("Controller PHY Device Info=0x%X\n", + le32_to_cpu(phy_data->ControllerPhyDeviceInfo)); + printk("DiscoveryStatus=0x%X\n", + le32_to_cpu(phy_data->DiscoveryStatus)); + printk("\n"); +} + +static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0) +{ + __le64 sas_address; + + memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); + + printk("---- SAS PHY PAGE 0 ------------\n"); + printk("Attached Device Handle=0x%X\n", + le16_to_cpu(pg0->AttachedDevHandle)); + printk("SAS Address=0x%llX\n", + (unsigned long long)le64_to_cpu(sas_address)); + printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier); + printk("Attached Device Info=0x%X\n", + le32_to_cpu(pg0->AttachedDeviceInfo)); + printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate); + printk("Change Count=0x%X\n", pg0->ChangeCount); + printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo)); + printk("\n"); +} + +static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) +{ + __le64 sas_address; + + memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); + + printk("---- SAS DEVICE PAGE 0 ---------\n"); + printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); + printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); + printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); + printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); + printk("Target ID=0x%X\n", pg0->TargetID); + printk("Bus=0x%X\n", pg0->Bus); + printk("PhyNum=0x%X\n", pg0->PhyNum); + printk("AccessStatus=0x%X\n", le16_to_cpu(pg0->AccessStatus)); + printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)); + printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags)); + printk("Physical Port=0x%X\n", pg0->PhysicalPort); + printk("\n"); +} + +static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) +{ + printk("---- SAS EXPANDER PAGE 1 ------------\n"); + + printk("Physical Port=0x%X\n", pg1->PhysicalPort); + printk("PHY Identifier=0x%X\n", pg1->Phy); + printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate); + printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate); + printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate); + printk("Owner Device Handle=0x%X\n", + le16_to_cpu(pg1->OwnerDevHandle)); + printk("Attached Device Handle=0x%X\n", + le16_to_cpu(pg1->AttachedDevHandle)); +} +#else +#define mptsas_print_phy_data(phy_data) do { } while (0) +#define mptsas_print_phy_pg0(pg0) do { } while (0) +#define mptsas_print_device_pg0(pg0) do { } while (0) +#define mptsas_print_expander_pg1(pg1) do { } while (0) +#endif + +static int +mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasIOUnitPage0_t *buffer; + dma_addr_t dma_handle; + int error, i; + + hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = 0; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + port_info->num_phys = buffer->NumPhys; + port_info->phy_info = kcalloc(port_info->num_phys, + sizeof(struct mptsas_phyinfo),GFP_KERNEL); + if (!port_info->phy_info) { + error = -ENOMEM; + goto out_free_consistent; + } + + for (i = 0; i < port_info->num_phys; i++) { + mptsas_print_phy_data(&buffer->PhyData[i]); + port_info->phy_info[i].phy_id = i; + port_info->phy_info[i].port_id = + buffer->PhyData[i].Port; + port_info->phy_info[i].negotiated_link_rate = + buffer->PhyData[i].NegotiatedLinkRate; + } + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasPhyPage0_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; + + cfg.cfghdr.ehdr = &hdr; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + /* Get Phy Pg 0 for each Phy. */ + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + mptsas_print_phy_pg0(buffer); + + phy_info->hw_link_rate = buffer->HwLinkRate; + phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; + phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); + phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasDevicePage0_t *buffer; + dma_addr_t dma_handle; + __le64 sas_address; + int error; + + hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; + + cfg.cfghdr.ehdr = &hdr; + cfg.pageAddr = form + form_specific; + cfg.physAddr = -1; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + mptsas_print_device_pg0(buffer); + + device_info->handle = le16_to_cpu(buffer->DevHandle); + device_info->phy_id = buffer->PhyNum; + device_info->port_id = buffer->PhysicalPort; + device_info->target = buffer->TargetID; + device_info->bus = buffer->Bus; + memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); + device_info->sas_address = le64_to_cpu(sas_address); + device_info->device_info = + le32_to_cpu(buffer->DeviceInfo); + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasExpanderPage0_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 0; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + /* save config data */ + port_info->num_phys = buffer->NumPhys; + port_info->handle = le16_to_cpu(buffer->DevHandle); + port_info->phy_info = kcalloc(port_info->num_phys, + sizeof(struct mptsas_phyinfo),GFP_KERNEL); + if (!port_info->phy_info) { + error = -ENOMEM; + goto out_free_consistent; + } + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static int +mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasExpanderPage1_t *buffer; + dma_addr_t dma_handle; + int error; + + hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; + hdr.ExtPageLength = 0; + hdr.PageNumber = 1; + hdr.Reserved1 = 0; + hdr.Reserved2 = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + + mptsas_print_expander_pg1(buffer); + + /* save config data */ + phy_info->phy_id = buffer->Phy; + phy_info->port_id = buffer->PhysicalPort; + phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate; + phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; + phy_info->hw_link_rate = buffer->HwLinkRate; + phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); + phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); + + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} + +static void +mptsas_parse_device_info(struct sas_identify *identify, + struct mptsas_devinfo *device_info) +{ + u16 protocols; + + identify->sas_address = device_info->sas_address; + identify->phy_identifier = device_info->phy_id; + + /* + * Fill in Phy Initiator Port Protocol. + * Bits 6:3, more than one bit can be set, fall through cases. + */ + protocols = device_info->device_info & 0x78; + identify->initiator_port_protocols = 0; + if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; + if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_STP; + if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR) + identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; + if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST) + identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; + + /* + * Fill in Phy Target Port Protocol. + * Bits 10:7, more than one bit can be set, fall through cases. + */ + protocols = device_info->device_info & 0x780; + identify->target_port_protocols = 0; + if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SSP; + if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_STP; + if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET) + identify->target_port_protocols |= SAS_PROTOCOL_SMP; + if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE) + identify->target_port_protocols |= SAS_PROTOCOL_SATA; + + /* + * Fill in Attached device type. + */ + switch (device_info->device_info & + MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { + case MPI_SAS_DEVICE_INFO_NO_DEVICE: + identify->device_type = SAS_PHY_UNUSED; + break; + case MPI_SAS_DEVICE_INFO_END_DEVICE: + identify->device_type = SAS_END_DEVICE; + break; + case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: + identify->device_type = SAS_EDGE_EXPANDER_DEVICE; + break; + case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: + identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; + break; + } +} + +static int mptsas_probe_one_phy(struct device *dev, + struct mptsas_phyinfo *phy_info, int index) +{ + struct sas_phy *port; + int error; + + port = sas_phy_alloc(dev, index); + if (!port) + return -ENOMEM; + + port->port_identifier = phy_info->port_id; + mptsas_parse_device_info(&port->identify, &phy_info->identify); + + /* + * Set Negotiated link rate. + */ + switch (phy_info->negotiated_link_rate) { + case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: + port->negotiated_linkrate = SAS_PHY_DISABLED; + break; + case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: + port->negotiated_linkrate = SAS_LINK_RATE_FAILED; + break; + case MPI_SAS_IOUNIT0_RATE_1_5: + port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_IOUNIT0_RATE_3_0: + port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: + case MPI_SAS_IOUNIT0_RATE_UNKNOWN: + default: + port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; + break; + } + + /* + * Set Max hardware link rate. + */ + switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { + case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: + port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: + port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Max programmed link rate. + */ + switch (phy_info->programmed_link_rate & + MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { + case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: + port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: + port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Min hardware link rate. + */ + switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { + case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: + port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: + port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + /* + * Set Min programmed link rate. + */ + switch (phy_info->programmed_link_rate & + MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { + case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: + port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; + break; + case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: + port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; + break; + default: + break; + } + + error = sas_phy_add(port); + if (error) { + sas_phy_free(port); + return error; + } + + if (phy_info->attached.handle) { + struct sas_rphy *rphy; + + rphy = sas_rphy_alloc(port); + if (!rphy) + return 0; /* non-fatal: an rphy can be added later */ + + mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + error = sas_rphy_add(rphy); + if (error) { + sas_rphy_free(rphy); + return error; + } + + phy_info->rphy = rphy; + } + + return 0; +} + +static int +mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) +{ + struct mptsas_portinfo *port_info; + u32 handle = 0xFFFF; + int error = -ENOMEM, i; + + port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + if (!port_info) + goto out; + memset(port_info, 0, sizeof(*port_info)); + + error = mptsas_sas_io_unit_pg0(ioc, port_info); + if (error) + goto out_free_port_info; + + list_add_tail(&port_info->list, &ioc->sas_topology); + + for (i = 0; i < port_info->num_phys; i++) { + mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], + (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << + MPI_SAS_PHY_PGAD_FORM_SHIFT), i); + + mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, + (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle); + handle = port_info->phy_info[i].identify.handle; + + if (port_info->phy_info[i].attached.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].attached, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].attached.handle); + } + + mptsas_probe_one_phy(&ioc->sh->shost_gendev, + &port_info->phy_info[i], *index); + (*index)++; + } + + return 0; + + out_free_port_info: + kfree(port_info); + out: + return error; +} + +static int +mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) +{ + struct mptsas_portinfo *port_info, *p; + int error = -ENOMEM, i, j; + + port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); + if (!port_info) + goto out; + memset(port_info, 0, sizeof(*port_info)); + + error = mptsas_sas_expander_pg0(ioc, port_info, + (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); + if (error) + goto out_free_port_info; + + *handle = port_info->handle; + + list_add_tail(&port_info->list, &ioc->sas_topology); + for (i = 0; i < port_info->num_phys; i++) { + struct device *parent; + + mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); + + if (port_info->phy_info[i].identify.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].identify, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].identify.handle); + } + + if (port_info->phy_info[i].attached.handle) { + mptsas_sas_device_pg0(ioc, + &port_info->phy_info[i].attached, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + port_info->phy_info[i].attached.handle); + } + + /* + * If we find a parent port handle this expander is + * attached to another expander, else it hangs of the + * HBA phys. + */ + parent = &ioc->sh->shost_gendev; + list_for_each_entry(p, &ioc->sas_topology, list) { + for (j = 0; j < p->num_phys; j++) { + if (port_info->phy_info[i].identify.handle == + p->phy_info[j].attached.handle) + parent = &p->phy_info[j].rphy->dev; + } + } + + mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index); + (*index)++; + } + + return 0; + + out_free_port_info: + kfree(port_info); + out: + return error; +} + +static void +mptsas_scan_sas_topology(MPT_ADAPTER *ioc) +{ + u32 handle = 0xFFFF; + int index = 0; + + mptsas_probe_hba_phys(ioc, &index); + while (!mptsas_probe_expander_phys(ioc, &handle, &index)) + ; +} + +static int +mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct Scsi_Host *sh; + MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; + int numSGE = 0; + int scale; + int ioc_cap; + u8 *mem; + int error=0; + int r; + + r = mpt_attach(pdev,id); + if (r) + return r; + + ioc = pci_get_drvdata(pdev); + ioc->DoneCtx = mptsasDoneCtx; + ioc->TaskCtx = mptsasTaskCtx; + ioc->InternalCtx = mptsasInternalCtx; + + /* Added sanity check on readiness of the MPT adapter. + */ + if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { + printk(MYIOC_s_WARN_FMT + "Skipping because it's not operational!\n", + ioc->name); + return -ENODEV; + } + + if (!ioc->active) { + printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + return -ENODEV; + } + + /* Sanity check - ensure at least 1 port is INITIATOR capable + */ + ioc_cap = 0; + for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) { + if (ioc->pfacts[ii].ProtocolFlags & + MPI_PORTFACTS_PROTOCOL_INITIATOR) + ioc_cap++; + } + + if (!ioc_cap) { + printk(MYIOC_s_WARN_FMT + "Skipping ioc=%p because SCSI Initiator mode " + "is NOT enabled!\n", ioc->name, ioc); + return -ENODEV; + } + + sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST)); + if (!sh) { + printk(MYIOC_s_WARN_FMT + "Unable to register controller with SCSI subsystem\n", + ioc->name); + return -1; + } + + spin_lock_irqsave(&ioc->FreeQlock, flags); + + /* Attach the SCSI Host to the IOC structure + */ + ioc->sh = sh; + + sh->io_port = 0; + sh->n_io_port = 0; + sh->irq = 0; + + /* set 16 byte cdb's */ + sh->max_cmd_len = 16; + + sh->max_id = ioc->pfacts->MaxDevices + 1; + + sh->transportt = mptsas_transport_template; + + sh->max_lun = MPT_LAST_LUN + 1; + sh->max_channel = 0; + sh->this_id = ioc->pfacts[0].PortSCSIID; + + /* Required entry. + */ + sh->unique_id = ioc->id; + + INIT_LIST_HEAD(&ioc->sas_topology); + + /* Verify that we won't exceed the maximum + * number of chain buffers + * We can optimize: ZZ = req_sz/sizeof(SGE) + * For 32bit SGE's: + * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ + * + (req_sz - 64)/sizeof(SGE) + * A slightly different algorithm is required for + * 64bit SGEs. + */ + scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); + if (sizeof(dma_addr_t) == sizeof(u64)) { + numSGE = (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + + sizeof(u32)); + } else { + numSGE = 1 + (scale - 1) * + (ioc->facts.MaxChainDepth-1) + scale + + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + + sizeof(u32)); + } + + if (numSGE < sh->sg_tablesize) { + /* Reset this value */ + dprintk((MYIOC_s_INFO_FMT + "Resetting sg_tablesize to %d from %d\n", + ioc->name, numSGE, sh->sg_tablesize)); + sh->sg_tablesize = numSGE; + } + + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + + hd = (MPT_SCSI_HOST *) sh->hostdata; + hd->ioc = ioc; + + /* SCSI needs scsi_cmnd lookup table! + * (with size equal to req_depth*PtrSz!) + */ + sz = ioc->req_depth * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptsas_probe_failed; + } + + memset(mem, 0, sz); + hd->ScsiLookup = (struct scsi_cmnd **) mem; + + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + + /* Allocate memory for the device structures. + * A non-Null pointer at an offset + * indicates a device exists. + * max_id = 1 + maximum id (hosts.h) + */ + sz = sh->max_id * sizeof(void *); + mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto mptsas_probe_failed; + } + + memset(mem, 0, sz); + hd->Targets = (VirtDevice **) mem; + + dprintk((KERN_INFO + " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + hd->resetPending = 0; + hd->abortSCpnt = NULL; + + /* Clear the pointer used to store + * single-threaded commands, i.e., those + * issued during a bus scan, dv and + * configuration pages. + */ + hd->cmdPtr = NULL; + + /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field + * and add_timer + */ + init_timer(&hd->timer); + hd->timer.data = (unsigned long) hd; + hd->timer.function = mptscsih_timer_expired; + + hd->mpt_pq_filter = mpt_pq_filter; + ioc->sas_data.ptClear = mpt_pt_clear; + + if (ioc->sas_data.ptClear==1) { + mptbase_sas_persist_operation( + ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); + } + + ddvprintk((MYIOC_s_INFO_FMT + "mpt_pq_filter %x mpt_pq_filter %x\n", + ioc->name, + mpt_pq_filter, + mpt_pq_filter)); + + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + + error = scsi_add_host(sh, &ioc->pcidev->dev); + if (error) { + dprintk((KERN_ERR MYNAM + "scsi_add_host failed\n")); + goto mptsas_probe_failed; + } + + mptsas_scan_sas_topology(ioc); + + return 0; + +mptsas_probe_failed: + + mptscsih_remove(pdev); + return error; +} + +static void __devexit mptsas_remove(struct pci_dev *pdev) +{ + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + struct mptsas_portinfo *p, *n; + + sas_remove_host(ioc->sh); + + list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { + list_del(&p->list); + kfree(p); + } + + mptscsih_remove(pdev); +} + +static struct pci_device_id mptsas_pci_table[] = { + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E, + PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, mptsas_pci_table); + + +static struct pci_driver mptsas_driver = { + .name = "mptsas", + .id_table = mptsas_pci_table, + .probe = mptsas_probe, + .remove = __devexit_p(mptsas_remove), + .shutdown = mptscsih_shutdown, +#ifdef CONFIG_PM + .suspend = mptscsih_suspend, + .resume = mptscsih_resume, +#endif +}; + +static int __init +mptsas_init(void) +{ + show_mptmod_ver(my_NAME, my_VERSION); + + mptsas_transport_template = + sas_attach_transport(&mptsas_transport_functions); + if (!mptsas_transport_template) + return -ENODEV; + + mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); + mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasInternalCtx = + mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); + + if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM + ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM + ": Registered for IOC reset notifications\n")); + } + + return pci_register_driver(&mptsas_driver); +} + +static void __exit +mptsas_exit(void) +{ + pci_unregister_driver(&mptsas_driver); + sas_release_transport(mptsas_transport_template); + + mpt_reset_deregister(mptsasDoneCtx); + mpt_event_deregister(mptsasDoneCtx); + + mpt_deregister(mptsasInternalCtx); + mpt_deregister(mptsasTaskCtx); + mpt_deregister(mptsasDoneCtx); +} + +module_init(mptsas_init); +module_exit(mptsas_exit); -- cgit v0.10.2 From 466544d8898fc87ed6e2e62ac14af7c50ab7a1a4 Mon Sep 17 00:00:00 2001 From: "Moore, Eric Dean" Date: Wed, 14 Sep 2005 18:09:10 -0600 Subject: [SCSI] fusion SAS support (mptsas driver) updates Summary of Changes: * splitting mpt_interrupt per Christophs suggestion about a month ago * rename ScsiCfgData to SpiCfgData structure, then move all the raid related info into new structure called RaidCfgData. This is done because SAS supports RAID, as well as SPI, so the raid stuff should be seperate. * incorrect timeout calculation for cntdn inside WaitForDoorbellAck and WaitForDoortbellInt * add support for interpreting SAS Log Info * Increase Event Log Size from 0xA to 0x32 * Fix bug in mptsas/mptfc/mptspi - when controller has Initiator Mode Disabled, and only running in TargetMode, the mptctl would panic when loading. The fix is to return 0, instead of -ENODEV, in SCSI LLD respective probe routines * Fix bug in mptlan.c - driver will panic if there is host reset, due to dev being set to zero in mpt_lan_ioc_reset * Fix's for SPI - Echo Buffer * Several fix's in mptscsih_io_done - FCP Response info, RESIDUAL_MISMATCH, Data Underrun, etc. * Cleanup Error Handling - EH handlers, mptscsih_flush_cmds, and zeroing out ScsiLookup from mptscsih_qcmd * Cleanup asyn event handling from mptscsih -> mptscsih_event_process. Also added support for SAS Persistent Table Full, an asyn event Signed-off-by: Eric Moore Signed-off-by: James Bottomley diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 14d62d9..790a293 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -135,7 +135,6 @@ static void mpt_adapter_dispose(MPT_ADAPTER *ioc); static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); -//static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); @@ -178,6 +177,7 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t * static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); +static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); /* module entry point */ static int __init fusion_init (void); @@ -209,6 +209,144 @@ pci_enable_io_access(struct pci_dev *pdev) pci_write_config_word(pdev, PCI_COMMAND, command_reg); } +/* + * Process turbo (context) reply... + */ +static void +mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) +{ + MPT_FRAME_HDR *mf = NULL; + MPT_FRAME_HDR *mr = NULL; + int req_idx = 0; + int cb_idx; + + dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", + ioc->name, pa)); + + switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { + case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT: + req_idx = pa & 0x0000FFFF; + cb_idx = (pa & 0x00FF0000) >> 16; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + break; + case MPI_CONTEXT_REPLY_TYPE_LAN: + cb_idx = mpt_lan_index; + /* + * Blind set of mf to NULL here was fatal + * after lan_reply says "freeme" + * Fix sort of combined with an optimization here; + * added explicit check for case where lan_reply + * was just returning 1 and doing nothing else. + * For this case skip the callback, but set up + * proper mf value first here:-) + */ + if ((pa & 0x58000000) == 0x58000000) { + req_idx = pa & 0x0000FFFF; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + mpt_free_msg_frame(ioc, mf); + mb(); + return; + break; + } + mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); + break; + case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET: + cb_idx = mpt_stm_index; + mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); + break; + default: + cb_idx = 0; + BUG(); + } + + /* Check for (valid) IO callback! */ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { + printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", + __FUNCTION__, ioc->name, cb_idx); + goto out; + } + + if (MptCallbacks[cb_idx](ioc, mf, mr)) + mpt_free_msg_frame(ioc, mf); + out: + mb(); +} + +static void +mpt_reply(MPT_ADAPTER *ioc, u32 pa) +{ + MPT_FRAME_HDR *mf; + MPT_FRAME_HDR *mr; + int req_idx; + int cb_idx; + int freeme; + + u32 reply_dma_low; + u16 ioc_stat; + + /* non-TURBO reply! Hmmm, something may be up... + * Newest turbo reply mechanism; get address + * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! + */ + + /* Map DMA address of reply header to cpu address. + * pa is 32 bits - but the dma address may be 32 or 64 bits + * get offset based only only the low addresses + */ + + reply_dma_low = (pa <<= 1); + mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + + (reply_dma_low - ioc->reply_frames_low_dma)); + + req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); + cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + + dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", + ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); + DBG_DUMP_REPLY_FRAME(mr) + + /* Check/log IOC log info + */ + ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); + if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { + u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); + if (ioc->bus_type == FC) + mpt_fc_log_info(ioc, log_info); + else if (ioc->bus_type == SCSI) + mpt_sp_log_info(ioc, log_info); + else if (ioc->bus_type == SAS) + mpt_sas_log_info(ioc, log_info); + } + if (ioc_stat & MPI_IOCSTATUS_MASK) { + if (ioc->bus_type == SCSI && + cb_idx != mpt_stm_index && + cb_idx != mpt_lan_index) + mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); + } + + + /* Check for (valid) IO callback! */ + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { + printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", + __FUNCTION__, ioc->name, cb_idx); + freeme = 0; + goto out; + } + + freeme = MptCallbacks[cb_idx](ioc, mf, mr); + + out: + /* Flush (non-TURBO) reply with a WRITE! */ + CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); + + if (freeme) + mpt_free_msg_frame(ioc, mf); + mb(); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. @@ -230,164 +368,21 @@ pci_enable_io_access(struct pci_dev *pdev) static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) { - MPT_ADAPTER *ioc; - MPT_FRAME_HDR *mf; - MPT_FRAME_HDR *mr; - u32 pa; - int req_idx; - int cb_idx; - int type; - int freeme; - - ioc = (MPT_ADAPTER *)bus_id; + MPT_ADAPTER *ioc = bus_id; + u32 pa; /* * Drain the reply FIFO! - * - * NOTES: I've seen up to 10 replies processed in this loop, so far... - * Update: I've seen up to 9182 replies processed in this loop! ?? - * Update: Limit ourselves to processing max of N replies - * (bottom of loop). */ while (1) { - - if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) + pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); + if (pa == 0xFFFFFFFF) return IRQ_HANDLED; - - cb_idx = 0; - freeme = 0; - - /* - * Check for non-TURBO reply! - */ - if (pa & MPI_ADDRESS_REPLY_A_BIT) { - u32 reply_dma_low; - u16 ioc_stat; - - /* non-TURBO reply! Hmmm, something may be up... - * Newest turbo reply mechanism; get address - * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! - */ - - /* Map DMA address of reply header to cpu address. - * pa is 32 bits - but the dma address may be 32 or 64 bits - * get offset based only only the low addresses - */ - reply_dma_low = (pa = (pa << 1)); - mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + - (reply_dma_low - ioc->reply_frames_low_dma)); - - req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); - cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - - dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", - ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); - DBG_DUMP_REPLY_FRAME(mr) - - /* Check/log IOC log info - */ - ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); - if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - if (ioc->bus_type == FC) - mpt_fc_log_info(ioc, log_info); - else if (ioc->bus_type == SCSI) - mpt_sp_log_info(ioc, log_info); - } - if (ioc_stat & MPI_IOCSTATUS_MASK) { - if (ioc->bus_type == SCSI) - mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); - } - } else { - /* - * Process turbo (context) reply... - */ - dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); - type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT); - if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) { - cb_idx = mpt_stm_index; - mf = NULL; - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) { - cb_idx = mpt_lan_index; - /* Blind set of mf to NULL here was fatal - * after lan_reply says "freeme" - * Fix sort of combined with an optimization here; - * added explicit check for case where lan_reply - * was just returning 1 and doing nothing else. - * For this case skip the callback, but set up - * proper mf value first here:-) - */ - if ((pa & 0x58000000) == 0x58000000) { - req_idx = pa & 0x0000FFFF; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - freeme = 1; - /* - * IMPORTANT! Invalidate the callback! - */ - cb_idx = 0; - } else { - mf = NULL; - } - mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); - } else { - req_idx = pa & 0x0000FFFF; - cb_idx = (pa & 0x00FF0000) >> 16; - mf = MPT_INDEX_2_MFPTR(ioc, req_idx); - mr = NULL; - } - pa = 0; /* No reply flush! */ - } - -#ifdef MPT_DEBUG_IRQ - if (ioc->bus_type == SCSI) { - /* Verify mf, mr are reasonable. - */ - if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) - || (mf < ioc->req_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid mf (%p)!\n", ioc->name, (void *)mf); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth)) - || (mr < ioc->reply_frames)) ) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr); - cb_idx = 0; - pa = 0; - freeme = 0; - } - if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) { - printk(MYIOC_s_WARN_FMT - "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx); - cb_idx = 0; - pa = 0; - freeme = 0; - } - } -#endif - - /* Check for (valid) IO callback! */ - if (cb_idx) { - /* Do the callback! */ - freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr); - } - - if (pa) { - /* Flush (non-TURBO) reply with a WRITE! */ - CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); - } - - if (freeme) { - /* Put Request back on FreeQ! */ - mpt_free_msg_frame(ioc, mf); - } - - mb(); - } /* drain reply FIFO */ + else if (pa & MPI_ADDRESS_REPLY_A_BIT) + mpt_reply(ioc, pa); + else + mpt_turbo_reply(ioc, pa); + } return IRQ_HANDLED; } @@ -1065,7 +1060,7 @@ mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_dma, - hst_page_buffer_sz)); + host_page_buffer_sz)); ioc->alloc_total += host_page_buffer_sz; ioc->HostPageBuffer_sz = host_page_buffer_sz; break; @@ -1208,7 +1203,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Initilize SCSI Config Data structure */ - memset(&ioc->spi_data, 0, sizeof(ScsiCfgData)); + memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); /* Initialize the running configQ head. */ @@ -1755,8 +1750,23 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) */ if (ret == 0) { rc = mpt_do_upload(ioc, sleepFlag); - if (rc != 0) + if (rc == 0) { + if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { + /* + * Maintain only one pointer to FW memory + * so there will not be two attempt to + * downloadboot onboard dual function + * chips (mpt_adapter_disable, + * mpt_diag_reset) + */ + ioc->cached_fw = NULL; + ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n", + ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); + } + } else { printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); + ret = -5; + } } } } @@ -1997,9 +2007,9 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) } kfree(ioc->spi_data.nvram); - kfree(ioc->spi_data.pIocPg3); + kfree(ioc->raid_data.pIocPg3); ioc->spi_data.nvram = NULL; - ioc->spi_data.pIocPg3 = NULL; + ioc->raid_data.pIocPg3 = NULL; if (ioc->spi_data.pIocPg4 != NULL) { sz = ioc->spi_data.IocPg4Sz; @@ -3852,7 +3862,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; u32 intstat=0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; + cntdn = 1000 * howlong; if (sleepFlag == CAN_SLEEP) { while (--cntdn) { @@ -3902,7 +3912,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) int count = 0; u32 intstat=0; - cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; + cntdn = 1000 * howlong; if (sleepFlag == CAN_SLEEP) { while (--cntdn) { intstat = CHIPREG_READ32(&ioc->chip->IntStatus); @@ -4634,10 +4644,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) if (mpt_config(ioc, &cfg) != 0) goto done_and_free; - if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) { + if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { mem = kmalloc(iocpage2sz, GFP_ATOMIC); if (mem) { - ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem; + ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; } else { goto done_and_free; } @@ -4654,7 +4664,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* At least 1 RAID Volume */ pIocRv = pIoc2->RaidVolume; - ioc->spi_data.isRaid = 0; + ioc->raid_data.isRaid = 0; for (jj = 0; jj < nVols; jj++, pIocRv++) { vid = pIocRv->VolumeID; vbus = pIocRv->VolumeBus; @@ -4663,7 +4673,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) /* find the match */ if (vbus == 0) { - ioc->spi_data.isRaid |= (1 << vid); + ioc->raid_data.isRaid |= (1 << vid); } else { /* Error! Always bus 0 */ @@ -4698,8 +4708,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) /* Free the old page */ - kfree(ioc->spi_data.pIocPg3); - ioc->spi_data.pIocPg3 = NULL; + kfree(ioc->raid_data.pIocPg3); + ioc->raid_data.pIocPg3 = NULL; /* There is at least one physical disk. * Read and save IOC Page 3 @@ -4736,7 +4746,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) mem = kmalloc(iocpage3sz, GFP_ATOMIC); if (mem) { memcpy(mem, (u8 *)pIoc3, iocpage3sz); - ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem; + ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; } } @@ -6022,6 +6032,111 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); } +/* strings for sas loginfo */ + static char *originator_str[] = { + "IOP", /* 00h */ + "PL", /* 01h */ + "IR" /* 02h */ + }; + static char *iop_code_str[] = { + NULL, /* 00h */ + "Invalid SAS Address", /* 01h */ + NULL, /* 02h */ + "Invalid Page", /* 03h */ + NULL, /* 04h */ + "Task Terminated" /* 05h */ + }; + static char *pl_code_str[] = { + NULL, /* 00h */ + "Open Failure", /* 01h */ + "Invalid Scatter Gather List", /* 02h */ + "Wrong Relative Offset or Frame Length", /* 03h */ + "Frame Transfer Error", /* 04h */ + "Transmit Frame Connected Low", /* 05h */ + "SATA Non-NCQ RW Error Bit Set", /* 06h */ + "SATA Read Log Receive Data Error", /* 07h */ + "SATA NCQ Fail All Commands After Error", /* 08h */ + "SATA Error in Receive Set Device Bit FIS", /* 09h */ + "Receive Frame Invalid Message", /* 0Ah */ + "Receive Context Message Valid Error", /* 0Bh */ + "Receive Frame Current Frame Error", /* 0Ch */ + "SATA Link Down", /* 0Dh */ + "Discovery SATA Init W IOS", /* 0Eh */ + "Config Invalid Page", /* 0Fh */ + "Discovery SATA Init Timeout", /* 10h */ + "Reset", /* 11h */ + "Abort", /* 12h */ + "IO Not Yet Executed", /* 13h */ + "IO Executed", /* 14h */ + NULL, /* 15h */ + NULL, /* 16h */ + NULL, /* 17h */ + NULL, /* 18h */ + NULL, /* 19h */ + NULL, /* 1Ah */ + NULL, /* 1Bh */ + NULL, /* 1Ch */ + NULL, /* 1Dh */ + NULL, /* 1Eh */ + NULL, /* 1Fh */ + "Enclosure Management" /* 20h */ + }; + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* + * mpt_sas_log_info - Log information returned from SAS IOC. + * @ioc: Pointer to MPT_ADAPTER structure + * @log_info: U32 LogInfo reply word from the IOC + * + * Refer to lsi/mpi_log_sas.h. + */ +static void +mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) +{ +union loginfo_type { + u32 loginfo; + struct { + u32 subcode:16; + u32 code:8; + u32 originator:4; + u32 bus_type:4; + }dw; +}; + union loginfo_type sas_loginfo; + char *code_desc = NULL; + + sas_loginfo.loginfo = log_info; + if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) && + (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*))) + return; + if ((sas_loginfo.dw.originator == 0 /*IOP*/) && + (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) { + code_desc = iop_code_str[sas_loginfo.dw.code]; + }else if ((sas_loginfo.dw.originator == 1 /*PL*/) && + (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) { + code_desc = pl_code_str[sas_loginfo.dw.code]; + } + + if (code_desc != NULL) + printk(MYIOC_s_INFO_FMT + "LogInfo(0x%08x): Originator={%s}, Code={%s}," + " SubCode(0x%04x)\n", + ioc->name, + log_info, + originator_str[sas_loginfo.dw.originator], + code_desc, + sas_loginfo.dw.subcode); + else + printk(MYIOC_s_INFO_FMT + "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," + " SubCode(0x%04x)\n", + ioc->name, + log_info, + originator_str[sas_loginfo.dw.originator], + sas_loginfo.dw.code, + sas_loginfo.dw.subcode); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index bbd21d7..7510527 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -77,8 +77,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.03.02" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02" +#define MPT_LINUX_VERSION_COMMON "3.03.03" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.03" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -424,7 +424,7 @@ typedef struct _MPT_IOCTL { /* * Event Structure and define */ -#define MPTCTL_EVENT_LOG_SIZE (0x0000000A) +#define MPTCTL_EVENT_LOG_SIZE (0x000000032) typedef struct _mpt_ioctl_events { u32 event; /* Specified by define above */ u32 eventContext; /* Index or counter */ @@ -452,16 +452,13 @@ typedef struct _mpt_ioctl_events { #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ -typedef struct _ScsiCfgData { +typedef struct _SpiCfgData { u32 PortFlags; int *nvram; /* table of device NVRAM values */ - IOCPage2_t *pIocPg2; /* table of Raid Volumes */ - IOCPage3_t *pIocPg3; /* table of physical disks */ IOCPage4_t *pIocPg4; /* SEP devices addressing */ dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ int IocPg4Sz; /* IOCPage4 size */ u8 dvStatus[MPT_MAX_SCSI_DEVICES]; - int isRaid; /* bit field, 1 if RAID */ u8 minSyncFactor; /* 0xFF if async */ u8 maxSyncOffset; /* 0 if async */ u8 maxBusWidth; /* 0 if narrow, 1 if wide */ @@ -473,10 +470,14 @@ typedef struct _ScsiCfgData { u8 dvScheduled; /* 1 if scheduled */ u8 forceDv; /* 1 to force DV scheduling */ u8 noQas; /* Disable QAS for this adapter */ - u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */ + u8 Saf_Te; /* 1 to force all Processors as + * SAF-TE if Inquiry data length + * is too short to check for SAF-TE + */ u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ + u8 bus_reset; /* 1 to allow bus reset */ u8 rsvd[1]; -} ScsiCfgData; +}SpiCfgData; typedef struct _SasCfgData { u8 ptClear; /* 1 to automatically clear the @@ -486,6 +487,12 @@ typedef struct _SasCfgData { */ }SasCfgData; +typedef struct _RaidCfgData { + IOCPage2_t *pIocPg2; /* table of Raid Volumes */ + IOCPage3_t *pIocPg3; /* table of physical disks */ + int isRaid; /* bit field, 1 if RAID */ +}RaidCfgData; + /* * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS */ @@ -546,7 +553,8 @@ typedef struct _MPT_ADAPTER struct pci_dev *pcidev; /* struct pci_dev pointer */ u8 __iomem *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */ - ScsiCfgData spi_data; /* Scsi config. data */ + SpiCfgData spi_data; /* Scsi config. data */ + RaidCfgData raid_data; /* Raid config. data */ SasCfgData sas_data; /* Sas config. data */ MPT_IOCTL *ioctl; /* ioctl data pointer */ struct proc_dir_entry *ioc_dentry; diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 7577c24..cb2d59d 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1326,7 +1326,7 @@ mptctl_gettargetinfo (unsigned long arg) */ if (hd && hd->Targets) { mpt_findImVolumes(ioc); - pIoc2 = ioc->spi_data.pIocPg2; + pIoc2 = ioc->raid_data.pIocPg2; for ( id = 0; id <= max_id; ) { if ( pIoc2 && pIoc2->NumActiveVolumes ) { if ( id == pIoc2->RaidVolume[0].VolumeID ) { @@ -1348,7 +1348,7 @@ mptctl_gettargetinfo (unsigned long arg) --maxWordsLeft; goto next_id; } else { - pIoc3 = ioc->spi_data.pIocPg3; + pIoc3 = ioc->raid_data.pIocPg3; for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) goto next_id; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 13771ab..a628be9 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -189,7 +189,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); - return -ENODEV; + return 0; } sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 52794be..ed3c891 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -312,7 +312,12 @@ static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { struct net_device *dev = ioc->netdev; - struct mpt_lan_priv *priv = netdev_priv(dev); + struct mpt_lan_priv *priv; + + if (dev == NULL) + return(1); + else + priv = netdev_priv(dev); dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 0d9a192..429820e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -980,7 +980,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode " "is NOT enabled!\n", ioc->name, ioc); - return -ENODEV; + return 0; } sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST)); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 58b5fde..8dd25aa 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -93,8 +93,9 @@ typedef struct _BIG_SENSE_BUF { #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */ +#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ +#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ +#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ @@ -159,6 +160,8 @@ int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); +static struct work_struct mptscsih_persistTask; + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); @@ -167,6 +170,7 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); +static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); #endif void mptscsih_remove(struct pci_dev *); @@ -606,11 +610,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); sc->resid = sc->request_bufflen - xfer_cnt; + /* + * if we get a data underrun indication, yet no data was + * transferred and the SCSI status indicates that the + * command was never started, change the data underrun + * to success + */ + if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && + (scsi_status == MPI_SCSI_STATUS_BUSY || + scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT || + scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) { + status = MPI_IOCSTATUS_SUCCESS; + } + dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" "resid=%d bufflen=%d xfer_cnt=%d\n", ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], - status, scsi_state, scsi_status, sc->resid, + status, scsi_state, scsi_status, sc->resid, sc->request_bufflen, xfer_cnt)); if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) @@ -619,8 +636,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) /* * Look for + dump FCP ResponseInfo[]! */ - if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { - printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n", + if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && + pScsiReply->ResponseInfo) { + printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + "FCP_ResponseInfo=%08xh\n", + ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], le32_to_cpu(pScsiReply->ResponseInfo)); } @@ -661,23 +681,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) break; case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ - if ( xfer_cnt >= sc->underflow ) { - /* Sufficient data transfer occurred */ + sc->resid = sc->request_bufflen - xfer_cnt; + if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) + sc->result=DID_SOFT_ERROR << 16; + else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; - } else if ( xfer_cnt == 0 ) { - /* A CRC Error causes this condition; retry */ - sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | - (CHECK_CONDITION << 1); - sc->sense_buffer[0] = 0x70; - sc->sense_buffer[2] = NO_SENSE; - sc->sense_buffer[12] = 0; - sc->sense_buffer[13] = 0; - } else { - sc->result = DID_SOFT_ERROR << 16; - } - dreplyprintk((KERN_NOTICE - "RESIDUAL_MISMATCH: result=%x on id=%d\n", - sc->result, sc->device->id)); + dreplyprintk((KERN_NOTICE + "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -692,7 +702,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ; } else { if (xfer_cnt < sc->underflow) { - sc->result = DID_SOFT_ERROR << 16; + if (scsi_status == SAM_STAT_BUSY) + sc->result = SAM_STAT_BUSY; + else + sc->result = DID_SOFT_ERROR << 16; } if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { /* What to do? @@ -717,8 +730,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ - scsi_status = pScsiReply->SCSIStatus; - sc->result = (DID_OK << 16) | scsi_status; + if (scsi_status == MPI_SCSI_STATUS_BUSY) + sc->result = (DID_BUS_BUSY << 16) | scsi_status; + else + sc->result = (DID_OK << 16) | scsi_status; if (scsi_state == 0) { ; } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { @@ -890,12 +905,13 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) SCSIIORequest_t *mf = NULL; int ii; int max = hd->ioc->req_depth; + struct scsi_cmnd *sc; dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", target, lun, max)); for (ii=0; ii < max; ii++) { - if (hd->ScsiLookup[ii] != NULL) { + if ((sc = hd->ScsiLookup[ii]) != NULL) { mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); @@ -910,9 +926,22 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) hd->ScsiLookup[ii] = NULL; mptscsih_freeChainBuffers(hd->ioc, ii); mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); + if (sc->use_sg) { + pci_unmap_sg(hd->ioc->pcidev, + (struct scatterlist *) sc->request_buffer, + sc->use_sg, + sc->sc_data_direction); + } else if (sc->request_bufflen) { + pci_unmap_single(hd->ioc->pcidev, + sc->SCp.dma_handle, + sc->request_bufflen, + sc->sc_data_direction); + } + sc->host_scribble = NULL; + sc->result = DID_NO_CONNECT << 16; + sc->scsi_done(sc); } } - return; } @@ -967,8 +996,10 @@ mptscsih_remove(struct pci_dev *pdev) unsigned long flags; int sz1; - if(!host) + if(!host) { + mpt_detach(pdev); return; + } scsi_remove_host(host); @@ -1422,6 +1453,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return 0; fail: + hd->ScsiLookup[my_idx] = NULL; mptscsih_freeChainBuffers(hd->ioc, my_idx); mpt_free_msg_frame(hd->ioc, mf); return SCSI_MLQUEUE_HOST_BUSY; @@ -1709,24 +1741,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) MPT_FRAME_HDR *mf; u32 ctx2abort; int scpnt_idx; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: " + dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: " "Can't locate host! (sc=%p)\n", SCpnt)); return FAILED; } ioc = hd->ioc; - if (hd->resetPending) + if (hd->resetPending) { return FAILED; - - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", - hd->ioc->name, SCpnt); + } if (hd->timeouts < -1) hd->timeouts++; @@ -1734,16 +1765,20 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { - /* Cmd not found in ScsiLookup. + /* Cmd not found in ScsiLookup. * Do OS callback. */ SCpnt->result = DID_RESET << 16; - dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " + dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", hd->ioc->name, SCpnt)); return SUCCESS; } + printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", + hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); + /* Most important! Set TaskMsgContext to SCpnt's MsgContext! * (the IO to be ABORT'd) * @@ -1756,38 +1791,22 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, - ctx2abort, 2 /* 2 second timeout */) - < 0) { + ctx2abort, 2 /* 2 second timeout */); - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", - hd->ioc->name, SCpnt); + printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); - /* We must clear our pending flag before clearing our state. - */ + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - - /* Unmap the DMA buffers, if any. */ - if (SCpnt->use_sg) { - pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, - SCpnt->use_sg, SCpnt->sc_data_direction); - } else if (SCpnt->request_bufflen) { - pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle, - SCpnt->request_bufflen, SCpnt->sc_data_direction); - } - hd->ScsiLookup[scpnt_idx] = NULL; - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - mptscsih_freeChainBuffers(ioc, scpnt_idx); - mpt_free_msg_frame(ioc, mf); - return FAILED; } - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1803,11 +1822,12 @@ int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: " + dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: " "Can't locate host! (sc=%p)\n", SCpnt)); return FAILED; @@ -1816,24 +1836,26 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) if (hd->resetPending) return FAILED; - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", + printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n", hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, SCpnt->device->channel, SCpnt->device->id, - 0, 0, 5 /* 5 second timeout */) - < 0){ - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); + 0, 0, 5 /* 5 second timeout */); + + printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); + + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - return FAILED; } - - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1849,41 +1871,39 @@ int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; - spinlock_t *host_lock = SCpnt->device->host->host_lock; + int retval; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: " + dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: " "Can't locate host! (sc=%p)\n", SCpnt ) ); return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", + printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n", hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); if (hd->timeouts < -1) hd->timeouts++; - /* We are now ready to execute the task management request. */ - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */) - < 0){ + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, + SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */); - /* The TM request failed and the subsequent FW-reload failed! - * Fatal error case. - */ - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt request (sc=%p)\n", - hd->ioc->name, SCpnt); + printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", + hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); + + if (retval == 0) + return SUCCESS; + + if(retval != FAILED ) { hd->tmPending = 0; hd->tmState = TM_STATE_NONE; - spin_lock_irq(host_lock); - return FAILED; } - - return SUCCESS; + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2165,7 +2185,7 @@ mptscsih_slave_alloc(struct scsi_device *device) vdev->raidVolume = 0; hd->Targets[device->id] = vdev; if (hd->ioc->bus_type == SCSI) { - if (hd->ioc->spi_data.isRaid & (1 << device->id)) { + if (hd->ioc->raid_data.isRaid & (1 << device->id)) { vdev->raidVolume = 1; ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", device->id)); @@ -2180,22 +2200,6 @@ mptscsih_slave_alloc(struct scsi_device *device) return 0; } -static int -mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) -{ - int i; - - if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3) - return 0; - - for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) { - if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - - return 0; -} - /* * OS entry point to allow for host driver to free allocated memory * Called if no device present or device being unloaded @@ -2223,7 +2227,7 @@ mptscsih_slave_destroy(struct scsi_device *device) hd->Targets[target] = NULL; if (hd->ioc->bus_type == SCSI) { - if (mptscsih_is_raid_volume(hd, target)) { + if (mptscsih_is_phys_disk(hd->ioc, target)) { hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; } else { hd->ioc->spi_data.dvStatus[target] = @@ -2436,6 +2440,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_SCSI_HOST *hd; unsigned long flags; + int ii; dtmprintk((KERN_WARNING MYNAM ": IOC %s_reset routed to SCSI host driver!\n", @@ -2493,11 +2498,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /* ScsiLookup initialization */ - { - int ii; - for (ii=0; ii < hd->ioc->req_depth; ii++) - hd->ScsiLookup[ii] = NULL; - } + for (ii=0; ii < hd->ioc->req_depth; ii++) + hd->ScsiLookup[ii] = NULL; /* 2. Chain Buffer initialization */ @@ -2546,6 +2548,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* work queue thread to clear the persitency table */ +static void +mptscsih_sas_persist_clear_table(void * arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); +} + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { @@ -2555,18 +2567,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + return 1; + switch (event) { case MPI_EVENT_UNIT_ATTENTION: /* 03 */ /* FIXME! */ break; case MPI_EVENT_IOC_BUS_RESET: /* 04 */ case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - hd = NULL; - if (ioc->sh) { - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) - hd->soft_resets++; - } + if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) + hd->soft_resets++; break; case MPI_EVENT_LOGOUT: /* 09 */ /* FIXME! */ @@ -2585,69 +2597,24 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) break; case MPI_EVENT_INTEGRATED_RAID: /* 0B */ + { + pMpiEventDataRaid_t pRaidEventData = + (pMpiEventDataRaid_t) pEvReply->Data; #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION - /* negoNvram set to 0 if DV enabled and to USE_NVRAM if - * if DV disabled. Need to check for target mode. - */ - hd = NULL; - if (ioc->sh) - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - - if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) { - ScsiCfgData *pSpi; - Ioc3PhysDisk_t *pPDisk; - int numPDisk; - u8 reason; - u8 physDiskNum; - - reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; - if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { - /* New or replaced disk. - * Set DV flag and schedule DV. - */ - pSpi = &ioc->spi_data; - physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; - ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum)); - if (pSpi->pIocPg3) { - pPDisk = pSpi->pIocPg3->PhysDisk; - numPDisk =pSpi->pIocPg3->NumPhysDisks; - - while (numPDisk) { - if (physDiskNum == pPDisk->PhysDiskNum) { - pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); - pSpi->forceDv = MPT_SCSICFG_NEED_DV; - ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); - break; - } - pPDisk++; - numPDisk--; - } - - if (numPDisk == 0) { - /* The physical disk that needs DV was not found - * in the stored IOC Page 3. The driver must reload - * this page. DV routine will set the NEED_DV flag for - * all phys disks that have DV_NOT_DONE set. - */ - pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; - ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); - } - } - } - } + /* Domain Validation Needed */ + if (ioc->bus_type == SCSI && + pRaidEventData->ReasonCode == + MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) + mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); #endif + break; + } -#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) - printk("Raid Event RF: "); - { - u32 *m = (u32 *)pEvReply; - int ii; - int n = (int)pEvReply->MsgLength; - for (ii=6; ii < n; ii++) - printk(" %08x", le32_to_cpu(m[ii])); - printk("\n"); - } -#endif + /* Persistent table is full. */ + case MPI_EVENT_PERSISTENT_TABLE_FULL: + INIT_WORK(&mptscsih_persistTask, + mptscsih_sas_persist_clear_table,(void *)ioc); + schedule_work(&mptscsih_persistTask); break; case MPI_EVENT_NONE: /* 00 */ @@ -2684,7 +2651,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * { int indexed_lun, lun_index; VirtDevice *vdev; - ScsiCfgData *pSpi; + SpiCfgData *pSpi; char data_56; dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", @@ -2791,7 +2758,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) { - ScsiCfgData *pspi_data = &hd->ioc->spi_data; + SpiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->target_id; int nvram; VirtDevice *vdev; @@ -2970,11 +2937,13 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) { + MPT_ADAPTER *ioc = hd->ioc; u8 cmd; - ScsiCfgData *pSpi; + SpiCfgData *pSpi; - ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", - pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); + ddvtprintk((MYIOC_s_NOTE_FMT + " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", + hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) return; @@ -2982,12 +2951,12 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) cmd = pReq->CDB[0]; if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { - pSpi = &hd->ioc->spi_data; - if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) { + pSpi = &ioc->spi_data; + if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) { /* Set NEED_DV for all hidden disks */ - Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk; - int numPDisk = pSpi->pIocPg3->NumPhysDisks; + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; @@ -3001,6 +2970,50 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) } } +/* mptscsih_raid_set_dv_flags() + * + * New or replaced disk. Set DV flag and schedule DV. + */ +static void +mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) +{ + MPT_ADAPTER *ioc = hd->ioc; + SpiCfgData *pSpi = &ioc->spi_data; + Ioc3PhysDisk_t *pPDisk; + int numPDisk; + + if (hd->negoNvram != 0) + return; + + ddvtprintk(("DV requested for phys disk id %d\n", id)); + if (ioc->raid_data.pIocPg3) { + pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; + while (numPDisk) { + if (id == pPDisk->PhysDiskNum) { + pSpi->dvStatus[pPDisk->PhysDiskID] = + (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); + pSpi->forceDv = MPT_SCSICFG_NEED_DV; + ddvtprintk(("NEED_DV set for phys disk id %d\n", + pPDisk->PhysDiskID)); + break; + } + pPDisk++; + numPDisk--; + } + + if (numPDisk == 0) { + /* The physical disk that needs DV was not found + * in the stored IOC Page 3. The driver must reload + * this page. DV routine will set the NEED_DV flag for + * all phys disks that have DV_NOT_DONE set. + */ + pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; + ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); + } + } +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * If no Target, bus reset on 1st I/O. Set the flag to @@ -3088,7 +3101,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) MPT_ADAPTER *ioc = hd->ioc; Config_t *pReq; SCSIDevicePage1_t *pData; - VirtDevice *pTarget; + VirtDevice *pTarget=NULL; MPT_FRAME_HDR *mf; dma_addr_t dataDma; u16 req_idx; @@ -3187,7 +3200,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) #endif if (flags & MPT_SCSICFG_BLK_NEGO) - negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; + negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; mptscsih_setDevicePage1Flags(width, factor, offset, &requested, &configuration, negoFlags); @@ -4008,7 +4021,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) /* If target Ptr NULL or if this target is NOT a disk, skip. */ - if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){ + if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){ for (lun=0; lun <= MPT_LAST_LUN; lun++) { /* If LUN present, issue the command */ @@ -4103,9 +4116,9 @@ mptscsih_domainValidation(void *arg) if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { mpt_read_ioc_pg_3(ioc); - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + if (ioc->raid_data.pIocPg3) { + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) @@ -4144,7 +4157,7 @@ mptscsih_domainValidation(void *arg) isPhysDisk = mptscsih_is_phys_disk(ioc, id); if (isPhysDisk) { for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { + if (hd->ioc->raid_data.isRaid & (1 << ii)) { hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; } } @@ -4163,7 +4176,7 @@ mptscsih_domainValidation(void *arg) if (isPhysDisk) { for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { - if (hd->ioc->spi_data.isRaid & (1 << ii)) { + if (hd->ioc->raid_data.isRaid & (1 << ii)) { hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; } } @@ -4185,21 +4198,21 @@ mptscsih_domainValidation(void *arg) /* Search IOC page 3 to determine if this is hidden physical disk */ -static int +/* Search IOC page 3 to determine if this is hidden physical disk + */ +static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) { - if (ioc->spi_data.pIocPg3) { - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + int i; - while (numPDisk) { - if (pPDisk->PhysDiskID == id) { - return 1; - } - pPDisk++; - numPDisk--; - } + if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) + return 0; + + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; } + return 0; } @@ -4405,7 +4418,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* Skip this ID? Set cfg.cfghdr.hdr to force config page write */ { - ScsiCfgData *pspi_data = &hd->ioc->spi_data; + SpiCfgData *pspi_data = &hd->ioc->spi_data; if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { /* Set the factor from nvram */ nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; @@ -4435,11 +4448,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } /* Finish iocmd inititialization - hidden or visible disk? */ - if (ioc->spi_data.pIocPg3) { + if (ioc->raid_data.pIocPg3) { /* Search IOC page 3 for matching id */ - Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; - int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; + Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; + int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; while (numPDisk) { if (pPDisk->PhysDiskID == id) { @@ -4463,7 +4476,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) /* RAID Volume ID's may double for a physical device. If RAID but * not a physical ID as well, skip DV. */ - if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) + if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) goto target_done; @@ -4812,6 +4825,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) notDone = 0; if (iocmd.flags & MPT_ICFLAG_ECHO) { bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; + if (pbuf1[0] & 0x01) + iocmd.flags |= MPT_ICFLAG_EBOS; } else { bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; } @@ -4908,6 +4923,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } iocmd.flags &= ~MPT_ICFLAG_DID_RESET; + if (iocmd.flags & MPT_ICFLAG_EBOS) + goto skip_Reserve; + repeat = 5; while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { iocmd.cmd = RESERVE; @@ -4951,6 +4969,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) } } +skip_Reserve: mptscsih_fillbuf(pbuf1, sz, patt, 1); iocmd.cmd = WRITE_BUFFER; iocmd.data_dma = buf1_dma; @@ -5195,11 +5214,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) * If not an LVD bus, the adapter minSyncFactor has been * already throttled back. */ + negoFlags = hd->ioc->spi_data.noQas; if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) { width = pTarget->maxWidth; offset = pTarget->maxOffset; factor = pTarget->minSyncFactor; - negoFlags = pTarget->negoFlags; + negoFlags |= pTarget->negoFlags; } else { if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { data = hd->ioc->spi_data.nvram[id]; @@ -5220,7 +5240,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) } /* Set the negotiation flags */ - negoFlags = hd->ioc->spi_data.noQas; if (!width) negoFlags |= MPT_TARGET_NO_NEGO_WIDE; diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 51c0255..09389af 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -1,5 +1,5 @@ /* - * linux/drivers/message/fusion/mptscsi.h + * linux/drivers/message/fusion/mptscsih.h * High performance SCSI / Fibre Channel SCSI Host device driver. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel @@ -53,8 +53,8 @@ * SCSI Public stuff... */ -#define MPT_SCSI_CMD_PER_DEV_HIGH 31 -#define MPT_SCSI_CMD_PER_DEV_LOW 7 +#define MPT_SCSI_CMD_PER_DEV_HIGH 64 +#define MPT_SCSI_CMD_PER_DEV_LOW 32 #define MPT_SCSI_CMD_PER_LUN 7 @@ -77,6 +77,7 @@ #define MPTSCSIH_MAX_WIDTH 1 #define MPTSCSIH_MIN_SYNC 0x08 #define MPTSCSIH_SAF_TE 0 +#define MPTSCSIH_PT_CLEAR 0 #endif @@ -105,3 +106,4 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); +extern void scsi_print_command(struct scsi_cmnd *cmd); diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 587d127..5c0e307 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -199,7 +199,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); - return -ENODEV; + return 0; } sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); -- cgit v0.10.2 From e0fc15bef0e8c6b5abad6e10cfe3d42e278ae8e8 Mon Sep 17 00:00:00 2001 From: "Moore, Eric Dean" Date: Thu, 15 Sep 2005 13:17:14 -0600 Subject: [SCSI] fusion SAS support (mptsas driver) minor fix On Thursday, September 15, 2005 6:22 AM, Christoph Hellwig wrote: > Looks good to me, except for the spurious scsi_print_command prototype > in mptscsih.h. The attached patch addresses that concern. Signed-off-by: Eric Moore Signed-off-by: James Bottomley diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 8dd25aa..5cb07eb2 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "mptbase.h" #include "mptscsih.h" diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 09389af..971fda4 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -106,4 +106,3 @@ extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pE extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); -extern void scsi_print_command(struct scsi_cmnd *cmd); -- cgit v0.10.2 From 3734d24b2e8d85796de70c13705cfb7cbb1d77df Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 13 Sep 2005 21:47:11 +0200 Subject: [SCSI] zfcp: fix race conditions when accessing erp_action lists o always use locking when changing erp_action lists, o avoid escalation to ERP_ACTION_REOPEN_PORT_FORCED if erp_action is still in use for ERP_ACTION_REOPEN_PORT Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cb4f612..376cb0f 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -886,7 +886,7 @@ static int zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) { int retval = 0; - struct zfcp_fsf_req *fsf_req; + struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_adapter *adapter = erp_action->adapter; if (erp_action->fsf_req) { @@ -896,7 +896,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) if (fsf_req == erp_action->fsf_req) break; - if (fsf_req == erp_action->fsf_req) { + if (fsf_req && (fsf_req->erp_action == erp_action)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); debug_event(adapter->erp_dbf, 3, &fsf_req, @@ -2291,7 +2291,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, &adapter->status); ZFCP_LOG_DEBUG("Doing exchange config data\n"); + write_lock(&adapter->erp_lock); zfcp_erp_action_to_running(erp_action); + write_unlock(&adapter->erp_lock); zfcp_erp_timeout_init(erp_action); if (zfcp_fsf_exchange_config_data(erp_action)) { retval = ZFCP_ERP_FAILED; @@ -3194,11 +3196,19 @@ zfcp_erp_action_enqueue(int action, /* fall through !!! */ case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - if (atomic_test_mask - (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status) - && port->erp_action.action == - ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { - debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp"); + if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, + &port->status)) { + if (port->erp_action.action != + ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { + ZFCP_LOG_INFO("dropped erp action %i (port " + "0x%016Lx, action in use: %i)\n", + action, port->wwpn, + port->erp_action.action); + debug_text_event(adapter->erp_dbf, 4, + "pf_actenq_drp"); + } else + debug_text_event(adapter->erp_dbf, 4, + "pf_actenq_drpcp"); debug_event(adapter->erp_dbf, 4, &port->wwpn, sizeof (wwn_t)); goto out; -- cgit v0.10.2 From 059c97d0434834d291eff94669ca2dd3eaac9d28 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 13 Sep 2005 21:47:52 +0200 Subject: [SCSI] zfcp: remove union zfcp_req_data, use unit refcount for FCP commands o union zfcp_req_data removed o increment unit refcount when processing FCP commands (This fixes a theoretical race: When all scsi commands of a unit are aborted and the scsi_device is removed then the unit could be removed before all fsf_requests of that unit are completely processed.) Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index bfe3ba7..17f9989 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -141,7 +141,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, spin_lock_irqsave(&adapter->dbf_lock, flags); if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { - scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd; + scsi_cmnd = (struct scsi_cmnd*) fsf_req->data; debug_text_event(adapter->cmd_dbf, level, "fsferror"); debug_text_event(adapter->cmd_dbf, level, text); debug_event(adapter->cmd_dbf, level, &fsf_req, @@ -167,14 +167,12 @@ void zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) { struct zfcp_adapter *adapter; - union zfcp_req_data *req_data; struct zfcp_fsf_req *fsf_req; int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5); unsigned long flags; adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; - req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble; - fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL); + fsf_req = (struct zfcp_fsf_req *) scsi_cmnd->host_scribble; spin_lock_irqsave(&adapter->dbf_lock, flags); debug_text_event(adapter->cmd_dbf, level, "hostbyte"); debug_text_event(adapter->cmd_dbf, level, text); @@ -1609,7 +1607,7 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) u32 els_type; struct zfcp_adapter *adapter; - status_buffer = fsf_req->data.status_read.buffer; + status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; els_type = *(u32 *) (status_buffer->payload); adapter = fsf_req->adapter; diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 455e902..9160e68 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -635,45 +635,6 @@ struct zfcp_adapter_mempool { mempool_t *data_gid_pn; }; -struct zfcp_exchange_config_data{ -}; - -struct zfcp_open_port { - struct zfcp_port *port; -}; - -struct zfcp_close_port { - struct zfcp_port *port; -}; - -struct zfcp_open_unit { - struct zfcp_unit *unit; -}; - -struct zfcp_close_unit { - struct zfcp_unit *unit; -}; - -struct zfcp_close_physical_port { - struct zfcp_port *port; -}; - -struct zfcp_send_fcp_command_task { - struct zfcp_fsf_req *fsf_req; - struct zfcp_unit *unit; - struct scsi_cmnd *scsi_cmnd; - unsigned long start_jiffies; -}; - -struct zfcp_send_fcp_command_task_management { - struct zfcp_unit *unit; -}; - -struct zfcp_abort_fcp_command { - struct zfcp_fsf_req *fsf_req; - struct zfcp_unit *unit; -}; - /* * header for CT_IU */ @@ -781,33 +742,6 @@ struct zfcp_send_els { int status; }; -struct zfcp_status_read { - struct fsf_status_read_buffer *buffer; -}; - -struct zfcp_fsf_done { - struct completion *complete; - int status; -}; - -/* request specific data */ -union zfcp_req_data { - struct zfcp_exchange_config_data exchange_config_data; - struct zfcp_open_port open_port; - struct zfcp_close_port close_port; - struct zfcp_open_unit open_unit; - struct zfcp_close_unit close_unit; - struct zfcp_close_physical_port close_physical_port; - struct zfcp_send_fcp_command_task send_fcp_command_task; - struct zfcp_send_fcp_command_task_management - send_fcp_command_task_management; - struct zfcp_abort_fcp_command abort_fcp_command; - struct zfcp_send_ct *send_ct; - struct zfcp_send_els *send_els; - struct zfcp_status_read status_read; - struct fsf_qtcb_bottom_port *port_data; -}; - struct zfcp_qdio_queue { struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ u8 free_index; /* index of next free bfr @@ -963,11 +897,12 @@ struct zfcp_fsf_req { u32 fsf_command; /* FSF Command copy */ struct fsf_qtcb *qtcb; /* address of associated QTCB */ u32 seq_no; /* Sequence number of request */ - union zfcp_req_data data; /* Info fields of request */ + unsigned long data; /* private data of request */ struct zfcp_erp_action *erp_action; /* used if this request is issued on behalf of erp */ mempool_t *pool; /* used if request was alloacted from emergency pool */ + struct zfcp_unit *unit; }; typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c007b64..64e2c34 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -821,7 +821,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) goto failed_buf; } memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); - fsf_req->data.status_read.buffer = status_buffer; + fsf_req->data = (unsigned long) status_buffer; /* insert pointer to respective buffer */ sbale = zfcp_qdio_sbale_curr(fsf_req); @@ -859,7 +859,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) struct zfcp_port *port; unsigned long flags; - status_buffer = fsf_req->data.status_read.buffer; + status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; adapter = fsf_req->adapter; read_lock_irqsave(&zfcp_data.config_lock, flags); @@ -918,7 +918,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) int retval = 0; struct zfcp_adapter *adapter = fsf_req->adapter; struct fsf_status_read_buffer *status_buffer = - fsf_req->data.status_read.buffer; + (struct fsf_status_read_buffer *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { mempool_free(status_buffer, adapter->pool.data_status_read); @@ -1093,7 +1093,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id, sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; - fsf_req->data.abort_fcp_command.unit = unit; + fsf_req->data = (unsigned long) unit; /* set handles of unit and its parent port in QTCB */ fsf_req->qtcb->header.lun_handle = unit->handle; @@ -1139,7 +1139,7 @@ static int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) { int retval = -EINVAL; - struct zfcp_unit *unit = new_fsf_req->data.abort_fcp_command.unit; + struct zfcp_unit *unit; unsigned char status_qual = new_fsf_req->qtcb->header.fsf_status_qual.word[0]; @@ -1150,6 +1150,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) goto skip_fsfstatus; } + unit = (struct zfcp_unit *) new_fsf_req->data; + /* evaluate FSF status in QTCB */ switch (new_fsf_req->qtcb->header.fsf_status) { @@ -1414,7 +1416,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, fsf_req->qtcb->header.port_handle = port->handle; fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; fsf_req->qtcb->bottom.support.timeout = ct->timeout; - fsf_req->data.send_ct = ct; + fsf_req->data = (unsigned long) ct; /* start QDIO request for this FSF request */ ret = zfcp_fsf_req_send(fsf_req, ct->timer); @@ -1445,10 +1447,10 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, * zfcp_fsf_send_ct_handler - handler for Generic Service requests * @fsf_req: pointer to struct zfcp_fsf_req * - * Data specific for the Generic Service request is passed by - * fsf_req->data.send_ct - * Usually a specific handler for the request is called via - * fsf_req->data.send_ct->handler at end of this function. + * Data specific for the Generic Service request is passed using + * fsf_req->data. There we find the pointer to struct zfcp_send_ct. + * Usually a specific handler for the CT request is called which is + * found in this structure. */ static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) @@ -1462,7 +1464,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) u16 subtable, rule, counter; adapter = fsf_req->adapter; - send_ct = fsf_req->data.send_ct; + send_ct = (struct zfcp_send_ct *) fsf_req->data; port = send_ct->port; header = &fsf_req->qtcb->header; bottom = &fsf_req->qtcb->bottom.support; @@ -1714,7 +1716,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) fsf_req->qtcb->bottom.support.d_id = d_id; fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; - fsf_req->data.send_els = els; + fsf_req->data = (unsigned long) els; sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); @@ -1746,10 +1748,10 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) * zfcp_fsf_send_els_handler - handler for ELS commands * @fsf_req: pointer to struct zfcp_fsf_req * - * Data specific for the ELS command is passed by - * fsf_req->data.send_els - * Usually a specific handler for the command is called via - * fsf_req->data.send_els->handler at end of this function. + * Data specific for the ELS command is passed using + * fsf_req->data. There we find the pointer to struct zfcp_send_els. + * Usually a specific handler for the ELS command is called which is + * found in this structure. */ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) { @@ -1762,7 +1764,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) int retval = -EINVAL; u16 subtable, rule, counter; - send_els = fsf_req->data.send_els; + send_els = (struct zfcp_send_els *) fsf_req->data; adapter = send_els->adapter; port = send_els->port; d_id = send_els->d_id; @@ -2211,12 +2213,12 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, goto out; } + fsf_req->data = (unsigned long) data; + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; - fsf_req->data.port_data = data; - init_timer(timer); timer->function = zfcp_fsf_request_timeout_handler; timer->data = (unsigned long) adapter; @@ -2257,7 +2259,9 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) { struct fsf_qtcb_bottom_port *bottom; - struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data; + struct fsf_qtcb_bottom_port *data; + + data = (struct fsf_qtcb_bottom_port*) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) return; @@ -2312,7 +2316,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); - erp_action->fsf_req->data.open_port.port = erp_action->port; + erp_action->fsf_req->data = (unsigned long) erp_action->port; erp_action->fsf_req->erp_action = erp_action; /* start QDIO request for this FSF request */ @@ -2353,7 +2357,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) struct fsf_qtcb_header *header; u16 subtable, rule, counter; - port = fsf_req->data.open_port.port; + port = (struct zfcp_port *) fsf_req->data; header = &fsf_req->qtcb->header; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { @@ -2566,7 +2570,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); - erp_action->fsf_req->data.close_port.port = erp_action->port; + erp_action->fsf_req->data = (unsigned long) erp_action->port; erp_action->fsf_req->erp_action = erp_action; erp_action->fsf_req->qtcb->header.port_handle = erp_action->port->handle; @@ -2606,7 +2610,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) int retval = -EINVAL; struct zfcp_port *port; - port = fsf_req->data.close_port.port; + port = (struct zfcp_port *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change port status in our bookkeeping */ @@ -2703,7 +2707,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, &erp_action->port->status); /* save a pointer to this port */ - erp_action->fsf_req->data.close_physical_port.port = erp_action->port; + erp_action->fsf_req->data = (unsigned long) erp_action->port; /* port to be closeed */ erp_action->fsf_req->qtcb->header.port_handle = erp_action->port->handle; @@ -2747,7 +2751,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) struct fsf_qtcb_header *header; u16 subtable, rule, counter; - port = fsf_req->data.close_physical_port.port; + port = (struct zfcp_port *) fsf_req->data; header = &fsf_req->qtcb->header; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { @@ -2911,7 +2915,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->fsf_req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); - erp_action->fsf_req->data.open_unit.unit = erp_action->unit; + erp_action->fsf_req->data = (unsigned long) erp_action->unit; erp_action->fsf_req->erp_action = erp_action; /* start QDIO request for this FSF request */ @@ -2957,7 +2961,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) u16 subtable, rule, counter; u32 allowed, exclusive, readwrite; - unit = fsf_req->data.open_unit.unit; + unit = (struct zfcp_unit *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change unit status in our bookkeeping */ @@ -3242,7 +3246,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) erp_action->port->handle; erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); - erp_action->fsf_req->data.close_unit.unit = erp_action->unit; + erp_action->fsf_req->data = (unsigned long) erp_action->unit; erp_action->fsf_req->erp_action = erp_action; /* start QDIO request for this FSF request */ @@ -3281,7 +3285,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) int retval = -EINVAL; struct zfcp_unit *unit; - unit = fsf_req->data.close_unit.unit; /* restore unit */ + unit = (struct zfcp_unit *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change unit status in our bookkeeping */ @@ -3436,21 +3440,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, goto failed_req_create; } - /* - * associate FSF request with SCSI request - * (need this for look up on abort) - */ - fsf_req->data.send_fcp_command_task.fsf_req = fsf_req; - scsi_cmnd->host_scribble = (char *) &(fsf_req->data); + zfcp_unit_get(unit); + fsf_req->unit = unit; - /* - * associate SCSI command with FSF request - * (need this for look up on normal command completion) - */ - fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd; - fsf_req->data.send_fcp_command_task.start_jiffies = jiffies; - fsf_req->data.send_fcp_command_task.unit = unit; - ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun); + /* associate FSF request with SCSI request (for look up on abort) */ + scsi_cmnd->host_scribble = (char *) fsf_req; + + /* associate SCSI command with FSF request */ + fsf_req->data = (unsigned long) scsi_cmnd; /* set handles of unit and its parent port in QTCB */ fsf_req->qtcb->header.lun_handle = unit->handle; @@ -3584,6 +3581,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, send_failed: no_fit: failed_scsi_cmnd: + zfcp_unit_put(unit); zfcp_fsf_req_free(fsf_req); fsf_req = NULL; scsi_cmnd->host_scribble = NULL; @@ -3640,7 +3638,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, * hold a pointer to the unit being target of this * task management request */ - fsf_req->data.send_fcp_command_task_management.unit = unit; + fsf_req->data = (unsigned long) unit; /* set FSF related fields in QTCB */ fsf_req->qtcb->header.lun_handle = unit->handle; @@ -3706,9 +3704,9 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) header = &fsf_req->qtcb->header; if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) - unit = fsf_req->data.send_fcp_command_task_management.unit; + unit = (struct zfcp_unit *) fsf_req->data; else - unit = fsf_req->data.send_fcp_command_task.unit; + unit = fsf_req->unit; if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { /* go directly to calls of special handlers */ @@ -3947,6 +3945,8 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); } else { retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); + fsf_req->unit = NULL; + zfcp_unit_put(unit); } return retval; } @@ -3970,10 +3970,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) u32 sns_len; char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); unsigned long flags; - struct zfcp_unit *unit = fsf_req->data.send_fcp_command_task.unit; + struct zfcp_unit *unit = fsf_req->unit; read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); - scpnt = fsf_req->data.send_fcp_command_task.scsi_cmnd; + scpnt = (struct scsi_cmnd *) fsf_req->data; if (unlikely(!scpnt)) { ZFCP_LOG_DEBUG ("Command with fsf_req %p is not associated to " @@ -4198,8 +4198,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) &(fsf_req->qtcb->bottom.io.fcp_rsp); char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); - struct zfcp_unit *unit = - fsf_req->data.send_fcp_command_task_management.unit; + struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; del_timer(&fsf_req->adapter->scsi_er_timer); if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 31a7606..fffd123 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -414,67 +414,37 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) return (struct zfcp_port *) NULL; } -/* - * function: zfcp_scsi_eh_abort_handler - * - * purpose: tries to abort the specified (timed out) SCSI command - * - * note: We do not need to care for a SCSI command which completes - * normally but late during this abort routine runs. - * We are allowed to return late commands to the SCSI stack. - * It tracks the state of commands and will handle late commands. - * (Usually, the normal completion of late commands is ignored with - * respect to the running abort operation. Grep for 'done_late' - * in the SCSI stacks sources.) +/** + * zfcp_scsi_eh_abort_handler - abort the specified SCSI command + * @scpnt: pointer to scsi_cmnd to be aborted + * Return: SUCCESS - command has been aborted and cleaned up in internal + * bookkeeping, SCSI stack won't be called for aborted command + * FAILED - otherwise * - * returns: SUCCESS - command has been aborted and cleaned up in internal - * bookkeeping, - * SCSI stack won't be called for aborted command - * FAILED - otherwise + * We do not need to care for a SCSI command which completes normally + * but late during this abort routine runs. We are allowed to return + * late commands to the SCSI stack. It tracks the state of commands and + * will handle late commands. (Usually, the normal completion of late + * commands is ignored with respect to the running abort operation.) */ int -__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) +zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) { + struct Scsi_Host *scsi_host; + struct zfcp_adapter *adapter; + struct zfcp_unit *unit; int retval = SUCCESS; struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; - struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; - struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; - struct zfcp_port *port = unit->port; - struct Scsi_Host *scsi_host = scpnt->device->host; - union zfcp_req_data *req_data = NULL; unsigned long flags; - u32 status = 0; - - /* the components of a abort_dbf record (fixed size record) */ - u64 dbf_scsi_cmnd = (unsigned long) scpnt; - char dbf_opcode[ZFCP_ABORT_DBF_LENGTH]; - wwn_t dbf_wwn = port->wwpn; - fcp_lun_t dbf_fcp_lun = unit->fcp_lun; - u64 dbf_retries = scpnt->retries; - u64 dbf_allowed = scpnt->allowed; - u64 dbf_timeout = 0; - u64 dbf_fsf_req = 0; - u64 dbf_fsf_status = 0; - u64 dbf_fsf_qual[2] = { 0, 0 }; - char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; - - memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); - memcpy(dbf_opcode, - scpnt->cmnd, - min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH)); + + scsi_host = scpnt->device->host; + adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; + unit = (struct zfcp_unit *) scpnt->device->hostdata; ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n", scpnt, zfcp_get_busid_by_adapter(adapter)); - spin_unlock_irq(scsi_host->host_lock); - - /* - * Race condition between normal (late) completion and abort has - * to be avoided. - * The entirity of all accesses to scsi_req have to be atomic. - * scsi_req is usually part of the fsf_req and thus we block the - * release of fsf_req as long as we need to access scsi_req. - */ + /* avoid race condition between late normal completion and abort */ write_lock_irqsave(&adapter->abort_lock, flags); /* @@ -484,144 +454,48 @@ __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) * this routine returns. (scpnt is parameter passed to this routine * and must not disappear during abort even on late completion.) */ - req_data = (union zfcp_req_data *) scpnt->host_scribble; - /* DEBUG */ - ZFCP_LOG_DEBUG("req_data=%p\n", req_data); - if (!req_data) { - ZFCP_LOG_DEBUG("late command completion overtook abort\n"); - /* - * That's it. - * Do not initiate abort but return SUCCESS. - */ - write_unlock_irqrestore(&adapter->abort_lock, flags); - retval = SUCCESS; - strncpy(dbf_result, "##late1", ZFCP_ABORT_DBF_LENGTH); - goto out; - } - - /* Figure out which fsf_req needs to be aborted. */ - old_fsf_req = req_data->send_fcp_command_task.fsf_req; - - dbf_fsf_req = (unsigned long) old_fsf_req; - dbf_timeout = - (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ; - - ZFCP_LOG_DEBUG("old_fsf_req=%p\n", old_fsf_req); + old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; if (!old_fsf_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); ZFCP_LOG_NORMAL("bug: no old fsf request found\n"); - ZFCP_LOG_NORMAL("req_data:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) req_data, sizeof (union zfcp_req_data)); ZFCP_LOG_NORMAL("scsi_cmnd:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) scpnt, sizeof (struct scsi_cmnd)); retval = FAILED; - strncpy(dbf_result, "##bug:r", ZFCP_ABORT_DBF_LENGTH); goto out; } - old_fsf_req->data.send_fcp_command_task.scsi_cmnd = NULL; - /* mark old request as being aborted */ + old_fsf_req->data = 0; old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; - /* - * We have to collect all information (e.g. unit) needed by - * zfcp_fsf_abort_fcp_command before calling that routine - * since that routine is not allowed to access - * fsf_req which it is going to abort. - * This is because of we need to release fsf_req_list_lock - * before calling zfcp_fsf_abort_fcp_command. - * Since this lock will not be held, fsf_req may complete - * late and may be released meanwhile. - */ - ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit); - /* - * We block (call schedule) - * That's why we must release the lock and enable the - * interrupts before. - * On the other hand we do not need the lock anymore since - * all critical accesses to scsi_req are done. - */ + /* don't access old_fsf_req after releasing the abort_lock */ write_unlock_irqrestore(&adapter->abort_lock, flags); /* call FSF routine which does the abort */ new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, adapter, unit, 0); - ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req); if (!new_fsf_req) { retval = FAILED; ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd " "failed\n"); - strncpy(dbf_result, "##nores", ZFCP_ABORT_DBF_LENGTH); goto out; } /* wait for completion of abort */ - ZFCP_LOG_DEBUG("waiting for cleanup...\n"); -#if 1 - /* - * FIXME: - * copying zfcp_fsf_req_wait_and_cleanup code is not really nice - */ __wait_event(new_fsf_req->completion_wq, new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - status = new_fsf_req->status; - dbf_fsf_status = new_fsf_req->qtcb->header.fsf_status; - /* - * Ralphs special debug load provides timestamps in the FSF - * status qualifier. This might be specified later if being - * useful for debugging aborts. - */ - dbf_fsf_qual[0] = - *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; - dbf_fsf_qual[1] = - *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; zfcp_fsf_req_free(new_fsf_req); -#else - retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, - ZFCP_UNINTERRUPTIBLE, &status); -#endif - ZFCP_LOG_DEBUG("Waiting for cleanup complete, status=0x%x\n", status); + /* status should be valid since signals were not permitted */ - if (status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { + if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { retval = SUCCESS; - strncpy(dbf_result, "##succ", ZFCP_ABORT_DBF_LENGTH); - } else if (status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { + } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { retval = SUCCESS; - strncpy(dbf_result, "##late2", ZFCP_ABORT_DBF_LENGTH); } else { retval = FAILED; - strncpy(dbf_result, "##fail", ZFCP_ABORT_DBF_LENGTH); } - out: - debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH); - debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t)); - debug_event(adapter->abort_dbf, 1, &dbf_fcp_lun, sizeof (fcp_lun_t)); - debug_event(adapter->abort_dbf, 1, &dbf_retries, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_allowed, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_timeout, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_fsf_req, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_fsf_status, sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64)); - debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64)); - debug_text_event(adapter->abort_dbf, 1, dbf_result); - - spin_lock_irq(scsi_host->host_lock); return retval; } -int -zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) -{ - int rc; - struct Scsi_Host *scsi_host = scpnt->device->host; - spin_lock_irq(scsi_host->host_lock); - rc = __zfcp_scsi_eh_abort_handler(scpnt); - spin_unlock_irq(scsi_host->host_lock); - return rc; -} - /* * function: zfcp_scsi_eh_device_reset_handler * -- cgit v0.10.2 From 77eb1699c76177af2f3d65c8ae7934cf304e0254 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 13 Sep 2005 21:48:33 +0200 Subject: [SCSI] zfcp: remove function zfcp_fsf_req_wait_and_cleanup Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index cd98a2d..c400e3b 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -109,7 +109,6 @@ extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, struct zfcp_erp_action *); extern int zfcp_fsf_send_els(struct zfcp_send_els *); -extern int zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *); extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, struct zfcp_unit *, struct scsi_cmnd *, diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 64e2c34..929f6c9 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4548,52 +4548,6 @@ skip_fsfstatus: return retval; } - -/* - * function: zfcp_fsf_req_wait_and_cleanup - * - * purpose: - * - * FIXME(design): signal seems to be <0 !!! - * returns: 0 - request completed (*status is valid), cleanup succ. - * <0 - request completed (*status is valid), cleanup failed - * >0 - signal which interrupted waiting (*status invalid), - * request not completed, no cleanup - * - * *status is a copy of status of completed fsf_req - */ -int -zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req, - int interruptible, u32 * status) -{ - int retval = 0; - int signal = 0; - - if (interruptible) { - __wait_event_interruptible(fsf_req->completion_wq, - fsf_req->status & - ZFCP_STATUS_FSFREQ_COMPLETED, - signal); - if (signal) { - ZFCP_LOG_DEBUG("Caught signal %i while waiting for the " - "completion of the request at %p\n", - signal, fsf_req); - retval = signal; - goto out; - } - } else { - __wait_event(fsf_req->completion_wq, - fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - } - - *status = fsf_req->status; - - /* cleanup request */ - zfcp_fsf_req_free(fsf_req); - out: - return retval; -} - static inline int zfcp_fsf_req_sbal_check(unsigned long *flags, struct zfcp_qdio_queue *queue, int needed) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index fffd123..3b5d48c 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -558,9 +558,8 @@ static int zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) { struct zfcp_adapter *adapter = unit->port->adapter; - int retval; - int status; struct zfcp_fsf_req *fsf_req; + int retval = 0; /* issue task management function */ fsf_req = zfcp_fsf_send_fcp_command_task_management @@ -574,18 +573,16 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) goto out; } - retval = zfcp_fsf_req_wait_and_cleanup(fsf_req, - ZFCP_UNINTERRUPTIBLE, &status); - /* - * check completion status of task management function - * (status should always be valid since no signals permitted) - */ - if (status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) + __wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + + /* check completion status of task management function */ + if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) retval = -EIO; - else if (status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) + else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) retval = -ENOTSUPP; - else - retval = 0; + + zfcp_fsf_req_free(fsf_req); out: return retval; } -- cgit v0.10.2 From 810f1e3ea5cc0a812816af97020a27c73441f8e9 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 13 Sep 2005 21:49:52 +0200 Subject: [SCSI] zfcp: shorten eh_bus_reset and eh_host_reset handlers Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3b5d48c..eeb5152 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -587,50 +587,38 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) return retval; } -/* - * function: zfcp_scsi_eh_bus_reset_handler - * - * purpose: - * - * returns: +/** + * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) */ int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) { - int retval = 0; - struct zfcp_unit *unit; + struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; + struct zfcp_adapter *adapter = unit->port->adapter; - unit = (struct zfcp_unit *) scpnt->device->hostdata; ZFCP_LOG_NORMAL("bus reset because of problems with " "unit 0x%016Lx\n", unit->fcp_lun); - zfcp_erp_adapter_reopen(unit->port->adapter, 0); - zfcp_erp_wait(unit->port->adapter); - retval = SUCCESS; + zfcp_erp_adapter_reopen(adapter, 0); + zfcp_erp_wait(adapter); - return retval; + return SUCCESS; } -/* - * function: zfcp_scsi_eh_host_reset_handler - * - * purpose: - * - * returns: +/** + * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) */ int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { - int retval = 0; - struct zfcp_unit *unit; + struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; + struct zfcp_adapter *adapter = unit->port->adapter; - unit = (struct zfcp_unit *) scpnt->device->hostdata; ZFCP_LOG_NORMAL("host reset because of problems with " "unit 0x%016Lx\n", unit->fcp_lun); - zfcp_erp_adapter_reopen(unit->port->adapter, 0); - zfcp_erp_wait(unit->port->adapter); - retval = SUCCESS; + zfcp_erp_adapter_reopen(adapter, 0); + zfcp_erp_wait(adapter); - return retval; + return SUCCESS; } /* -- cgit v0.10.2 From 8a36e4532ea10471f0a8605207d071361d7be2c3 Mon Sep 17 00:00:00 2001 From: Maxim Shchetynin Date: Tue, 13 Sep 2005 21:50:38 +0200 Subject: [SCSI] zfcp: enhancement of zfcp debug features Debug features (DBFs) els_dbf, cmd_dbf and abt_dbf were removed and san_dbf, hba_dbf and scsi_dbf were introduced. The erp_dbf did not change. The new traces improve debugging of problems with zfcp, scsi-stack, multipath and hardware in the SAN. san_dbf traces things like ELS and CT commands, hba_dbf saves HBA specific information of requests, and scsi_dbf saves FCP and SCSI specific information of requests. Common to all new DBFs is that they provide a so called structured view. This significantly improves readability of the traces. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile index fc14530..d6a78f1 100644 --- a/drivers/s390/scsi/Makefile +++ b/drivers/s390/scsi/Makefile @@ -3,7 +3,7 @@ # zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ - zfcp_fsf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \ + zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \ zfcp_sysfs_unit.o zfcp_sysfs_driver.o obj-$(CONFIG_ZFCP) += zfcp.o diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 17f9989..0b5087f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -122,93 +122,6 @@ _zfcp_hex_dump(char *addr, int count) #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER -static inline int -zfcp_fsf_req_is_scsi_cmnd(struct zfcp_fsf_req *fsf_req) -{ - return ((fsf_req->fsf_command == FSF_QTCB_FCP_CMND) && - !(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)); -} - -void -zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, - void *add_data, int add_length) -{ - struct zfcp_adapter *adapter = fsf_req->adapter; - struct scsi_cmnd *scsi_cmnd; - int level = 3; - int i; - unsigned long flags; - - spin_lock_irqsave(&adapter->dbf_lock, flags); - if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { - scsi_cmnd = (struct scsi_cmnd*) fsf_req->data; - debug_text_event(adapter->cmd_dbf, level, "fsferror"); - debug_text_event(adapter->cmd_dbf, level, text); - debug_event(adapter->cmd_dbf, level, &fsf_req, - sizeof (unsigned long)); - debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no, - sizeof (u32)); - debug_event(adapter->cmd_dbf, level, &scsi_cmnd, - sizeof (unsigned long)); - debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, - min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); - for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH) - debug_event(adapter->cmd_dbf, - level, - (char *) add_data + i, - min(ZFCP_CMD_DBF_LENGTH, add_length - i)); - } - spin_unlock_irqrestore(&adapter->dbf_lock, flags); -} - -/* XXX additionally log unit if available */ -/* ---> introduce new parameter for unit, see 2.4 code */ -void -zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) -{ - struct zfcp_adapter *adapter; - struct zfcp_fsf_req *fsf_req; - int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5); - unsigned long flags; - - adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; - fsf_req = (struct zfcp_fsf_req *) scsi_cmnd->host_scribble; - spin_lock_irqsave(&adapter->dbf_lock, flags); - debug_text_event(adapter->cmd_dbf, level, "hostbyte"); - debug_text_event(adapter->cmd_dbf, level, text); - debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32)); - debug_event(adapter->cmd_dbf, level, &scsi_cmnd, - sizeof (unsigned long)); - debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, - min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); - if (likely(fsf_req)) { - debug_event(adapter->cmd_dbf, level, &fsf_req, - sizeof (unsigned long)); - debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no, - sizeof (u32)); - } else { - debug_text_event(adapter->cmd_dbf, level, ""); - debug_text_event(adapter->cmd_dbf, level, ""); - } - spin_unlock_irqrestore(&adapter->dbf_lock, flags); -} - -void -zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text, - struct fsf_status_read_buffer *status_buffer, int length) -{ - int level = 1; - int i; - - debug_text_event(adapter->in_els_dbf, level, text); - debug_event(adapter->in_els_dbf, level, &status_buffer->d_id, 8); - for (i = 0; i < length; i += ZFCP_IN_ELS_DBF_LENGTH) - debug_event(adapter->in_els_dbf, - level, - (char *) status_buffer->payload + i, - min(ZFCP_IN_ELS_DBF_LENGTH, length - i)); -} - /** * zfcp_device_setup - setup function * @str: pointer to parameter string @@ -1015,81 +928,6 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) mempool_destroy(adapter->pool.data_gid_pn); } -/** - * zfcp_adapter_debug_register - registers debug feature for an adapter - * @adapter: pointer to adapter for which debug features should be registered - * return: -ENOMEM on error, 0 otherwise - */ -int -zfcp_adapter_debug_register(struct zfcp_adapter *adapter) -{ - char dbf_name[20]; - - /* debug feature area which records SCSI command failures (hostbyte) */ - spin_lock_init(&adapter->dbf_lock); - - sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s", - zfcp_get_busid_by_adapter(adapter)); - adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX, - ZFCP_CMD_DBF_AREAS, - ZFCP_CMD_DBF_LENGTH); - debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view); - debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL); - - /* debug feature area which records SCSI command aborts */ - sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s", - zfcp_get_busid_by_adapter(adapter)); - adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX, - ZFCP_ABORT_DBF_AREAS, - ZFCP_ABORT_DBF_LENGTH); - debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view); - debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL); - - /* debug feature area which records incoming ELS commands */ - sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s", - zfcp_get_busid_by_adapter(adapter)); - adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX, - ZFCP_IN_ELS_DBF_AREAS, - ZFCP_IN_ELS_DBF_LENGTH); - debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view); - debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL); - - /* debug feature area which records erp events */ - sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s", - zfcp_get_busid_by_adapter(adapter)); - adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX, - ZFCP_ERP_DBF_AREAS, - ZFCP_ERP_DBF_LENGTH); - debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); - debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL); - - if (!(adapter->cmd_dbf && adapter->abort_dbf && - adapter->in_els_dbf && adapter->erp_dbf)) { - zfcp_adapter_debug_unregister(adapter); - return -ENOMEM; - } - - return 0; - -} - -/** - * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter - * @adapter: pointer to adapter for which debug features should be unregistered - */ -void -zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) -{ - debug_unregister(adapter->abort_dbf); - debug_unregister(adapter->cmd_dbf); - debug_unregister(adapter->erp_dbf); - debug_unregister(adapter->in_els_dbf); - adapter->abort_dbf = NULL; - adapter->cmd_dbf = NULL; - adapter->erp_dbf = NULL; - adapter->in_els_dbf = NULL; -} - void zfcp_dummy_release(struct device *dev) { @@ -1460,10 +1298,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, /* see FC-FS */ no_entries = (fcp_rscn_head->payload_len / 4); - zfcp_in_els_dbf_event(adapter, "##rscn", status_buffer, - fcp_rscn_head->payload_len); - - debug_text_event(adapter->erp_dbf, 1, "unsol_els_rscn:"); for (i = 1; i < no_entries; i++) { /* skip head and start with 1st element */ fcp_rscn_element++; @@ -1495,8 +1329,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, (ZFCP_STATUS_PORT_DID_DID, &port->status)) { ZFCP_LOG_INFO("incoming RSCN, trying to open " "port 0x%016Lx\n", port->wwpn); - debug_text_event(adapter->erp_dbf, 1, - "unsol_els_rscnu:"); zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); continue; @@ -1522,8 +1354,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, */ ZFCP_LOG_INFO("incoming RSCN, trying to open " "port 0x%016Lx\n", port->wwpn); - debug_text_event(adapter->erp_dbf, 1, - "unsol_els_rscnk:"); zfcp_test_link(port); } } @@ -1539,8 +1369,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, struct zfcp_port *port; unsigned long flags; - zfcp_in_els_dbf_event(adapter, "##plogi", status_buffer, 28); - read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) { if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn)) @@ -1554,8 +1382,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, status_buffer->d_id, zfcp_get_busid_by_adapter(adapter)); } else { - debug_text_event(adapter->erp_dbf, 1, "unsol_els_plogi:"); - debug_event(adapter->erp_dbf, 1, &els_logi->nport_wwn, 8); zfcp_erp_port_forced_reopen(port, 0); } } @@ -1568,8 +1394,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter, struct zfcp_port *port; unsigned long flags; - zfcp_in_els_dbf_event(adapter, "##logo", status_buffer, 16); - read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &adapter->port_list_head, list) { if (port->wwpn == els_logo->nport_wwpn) @@ -1583,8 +1407,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter, status_buffer->d_id, zfcp_get_busid_by_adapter(adapter)); } else { - debug_text_event(adapter->erp_dbf, 1, "unsol_els_logo:"); - debug_event(adapter->erp_dbf, 1, &els_logo->nport_wwpn, 8); zfcp_erp_port_forced_reopen(port, 0); } } @@ -1593,7 +1415,6 @@ static void zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { - zfcp_in_els_dbf_event(adapter, "##undef", status_buffer, 24); ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x " "for adapter %s\n", *(u32 *) (status_buffer->payload), zfcp_get_busid_by_adapter(adapter)); @@ -1611,6 +1432,7 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) els_type = *(u32 *) (status_buffer->payload); adapter = fsf_req->adapter; + zfcp_san_dbf_event_incoming_els(fsf_req); if (els_type == LS_PLOGI) zfcp_fsf_incoming_els_plogi(adapter, status_buffer); else if (els_type == LS_LOGO) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c new file mode 100644 index 0000000..fff1537 --- /dev/null +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -0,0 +1,988 @@ +/* + * + * linux/drivers/s390/scsi/zfcp_dbf.c + * + * FCP adapter driver for IBM eServer zSeries + * + * Debugging facilities + * + * (C) Copyright IBM Corp. 2005 + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define ZFCP_DBF_REVISION "$Revision$" + +#include +#include +#include "zfcp_ext.h" + +static u32 dbfsize = 4; + +module_param(dbfsize, uint, 0400); +MODULE_PARM_DESC(dbfsize, + "number of pages for each debug feature area (default 4)"); + +#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER + +static inline int +zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) +{ + unsigned long long sec; + struct timespec xtime; + int len = 0; + + stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); + sec = stck >> 12; + do_div(sec, 1000000); + xtime.tv_sec = sec; + stck -= (sec * 1000000) << 12; + xtime.tv_nsec = ((stck * 1000) >> 12); + len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", + label, xtime.tv_sec, xtime.tv_nsec); + + return len; +} + +static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag) +{ + int len = 0, i; + + len += sprintf(out_buf + len, "%-24s", label); + for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++) + len += sprintf(out_buf + len, "%c", tag[i]); + len += sprintf(out_buf + len, "\n"); + + return len; +} + +static int +zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...) +{ + va_list arg; + int len = 0; + + len += sprintf(out_buf + len, "%-24s", label); + va_start(arg, format); + len += vsprintf(out_buf + len, format, arg); + va_end(arg); + len += sprintf(out_buf + len, "\n"); + + return len; +} + +static int +zfcp_dbf_view_dump(char *out_buf, const char *label, + char *buffer, int buflen, int offset, int total_size) +{ + int len = 0; + + if (offset == 0) + len += sprintf(out_buf + len, "%-24s ", label); + + while (buflen--) { + if (offset > 0) { + if ((offset % 32) == 0) + len += sprintf(out_buf + len, "\n%-24c ", ' '); + else if ((offset % 4) == 0) + len += sprintf(out_buf + len, " "); + } + len += sprintf(out_buf + len, "%02x", *buffer++); + if (++offset == total_size) { + len += sprintf(out_buf + len, "\n"); + break; + } + } + + if (total_size == 0) + len += sprintf(out_buf + len, "\n"); + + return len; +} + +static inline int +zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, + debug_entry_t * entry, char *out_buf) +{ + struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry); + int len = 0; + + if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) { + len += zfcp_dbf_stck(out_buf + len, "timestamp", + entry->id.stck); + len += zfcp_dbf_view(out_buf + len, "cpu", "%02i", + entry->id.fields.cpuid); + } else { + len += zfcp_dbf_view_dump(out_buf + len, NULL, + dump->data, + dump->size, + dump->offset, dump->total_size); + if ((dump->offset + dump->size) == dump->total_size) + len += sprintf(out_buf + len, "\n"); + } + + return len; +} + +inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_qtcb *qtcb = fsf_req->qtcb; + union fsf_prot_status_qual *prot_status_qual = + &qtcb->prefix.prot_status_qual; + union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual; + struct scsi_cmnd *scsi_cmnd; + struct zfcp_port *port; + struct zfcp_unit *unit; + struct zfcp_send_els *send_els; + struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; + struct zfcp_hba_dbf_record_response *response = &rec->type.response; + int level; + unsigned long flags; + + spin_lock_irqsave(&adapter->hba_dbf_lock, flags); + memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); + strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE); + + if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && + (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { + strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE); + level = 1; + } else if (qtcb->header.fsf_status != FSF_GOOD) { + strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE); + level = 1; + } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || + (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) { + strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE); + level = 4; + } else if ((prot_status_qual->doubleword[0] != 0) || + (prot_status_qual->doubleword[1] != 0) || + (fsf_status_qual->doubleword[0] != 0) || + (fsf_status_qual->doubleword[1] != 0)) { + strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE); + level = 3; + } else { + strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE); + level = 6; + } + + response->fsf_command = fsf_req->fsf_command; + response->fsf_reqid = (unsigned long)fsf_req; + response->fsf_seqno = fsf_req->seq_no; + response->fsf_issued = fsf_req->issued; + response->fsf_prot_status = qtcb->prefix.prot_status; + response->fsf_status = qtcb->header.fsf_status; + memcpy(response->fsf_prot_status_qual, + prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE); + memcpy(response->fsf_status_qual, + fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); + response->fsf_req_status = fsf_req->status; + response->sbal_first = fsf_req->sbal_first; + response->sbal_curr = fsf_req->sbal_curr; + response->sbal_last = fsf_req->sbal_last; + response->pool = fsf_req->pool != NULL; + response->erp_action = (unsigned long)fsf_req->erp_action; + + switch (fsf_req->fsf_command) { + case FSF_QTCB_FCP_CMND: + if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) + break; + scsi_cmnd = (struct scsi_cmnd *)fsf_req->data; + if (scsi_cmnd != NULL) { + response->data.send_fcp.scsi_cmnd + = (unsigned long)scsi_cmnd; + response->data.send_fcp.scsi_serial + = scsi_cmnd->serial_number; + } + break; + + case FSF_QTCB_OPEN_PORT_WITH_DID: + case FSF_QTCB_CLOSE_PORT: + case FSF_QTCB_CLOSE_PHYSICAL_PORT: + port = (struct zfcp_port *)fsf_req->data; + response->data.port.wwpn = port->wwpn; + response->data.port.d_id = port->d_id; + response->data.port.port_handle = qtcb->header.port_handle; + break; + + case FSF_QTCB_OPEN_LUN: + case FSF_QTCB_CLOSE_LUN: + unit = (struct zfcp_unit *)fsf_req->data; + port = unit->port; + response->data.unit.wwpn = port->wwpn; + response->data.unit.fcp_lun = unit->fcp_lun; + response->data.unit.port_handle = qtcb->header.port_handle; + response->data.unit.lun_handle = qtcb->header.lun_handle; + break; + + case FSF_QTCB_SEND_ELS: + send_els = (struct zfcp_send_els *)fsf_req->data; + response->data.send_els.d_id = qtcb->bottom.support.d_id; + response->data.send_els.ls_code = send_els->ls_code >> 24; + break; + + case FSF_QTCB_ABORT_FCP_CMND: + case FSF_QTCB_SEND_GENERIC: + case FSF_QTCB_EXCHANGE_CONFIG_DATA: + case FSF_QTCB_EXCHANGE_PORT_DATA: + case FSF_QTCB_DOWNLOAD_CONTROL_FILE: + case FSF_QTCB_UPLOAD_CONTROL_FILE: + break; + } + + debug_event(adapter->hba_dbf, level, + rec, sizeof(struct zfcp_hba_dbf_record)); + spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); +} + +inline void +zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, + struct fsf_status_read_buffer *status_buffer) +{ + struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; + unsigned long flags; + + spin_lock_irqsave(&adapter->hba_dbf_lock, flags); + memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); + strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE); + strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE); + + rec->type.status.failed = adapter->status_read_failed; + if (status_buffer != NULL) { + rec->type.status.status_type = status_buffer->status_type; + rec->type.status.status_subtype = status_buffer->status_subtype; + memcpy(&rec->type.status.queue_designator, + &status_buffer->queue_designator, + sizeof(struct fsf_queue_designator)); + + switch (status_buffer->status_type) { + case FSF_STATUS_READ_SENSE_DATA_AVAIL: + rec->type.status.payload_size = + ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL; + break; + + case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: + rec->type.status.payload_size = + ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD; + break; + + case FSF_STATUS_READ_LINK_DOWN: + rec->type.status.payload_size = sizeof(u64); + break; + + } + memcpy(&rec->type.status.payload, + &status_buffer->payload, rec->type.status.payload_size); + } + + debug_event(adapter->hba_dbf, 2, + rec, sizeof(struct zfcp_hba_dbf_record)); + spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); +} + +inline void +zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, + unsigned int qdio_error, unsigned int siga_error, + int sbal_index, int sbal_count) +{ + struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; + unsigned long flags; + + spin_lock_irqsave(&adapter->hba_dbf_lock, flags); + memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); + strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE); + rec->type.qdio.status = status; + rec->type.qdio.qdio_error = qdio_error; + rec->type.qdio.siga_error = siga_error; + rec->type.qdio.sbal_index = sbal_index; + rec->type.qdio.sbal_count = sbal_count; + debug_event(adapter->hba_dbf, 0, + rec, sizeof(struct zfcp_hba_dbf_record)); + spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); +} + +static inline int +zfcp_hba_dbf_view_response(char *out_buf, + struct zfcp_hba_dbf_record_response *rec) +{ + int len = 0; + + len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x", + rec->fsf_command); + len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", + rec->fsf_reqid); + len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", + rec->fsf_seqno); + len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued); + len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x", + rec->fsf_prot_status); + len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x", + rec->fsf_status); + len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual", + rec->fsf_prot_status_qual, + FSF_PROT_STATUS_QUAL_SIZE, + 0, FSF_PROT_STATUS_QUAL_SIZE); + len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual", + rec->fsf_status_qual, + FSF_STATUS_QUALIFIER_SIZE, + 0, FSF_STATUS_QUALIFIER_SIZE); + len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x", + rec->fsf_req_status); + len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x", + rec->sbal_first); + len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x", + rec->sbal_curr); + len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x", + rec->sbal_last); + len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool); + + switch (rec->fsf_command) { + case FSF_QTCB_FCP_CMND: + if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) + break; + len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx", + rec->data.send_fcp.scsi_cmnd); + len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx", + rec->data.send_fcp.scsi_serial); + break; + + case FSF_QTCB_OPEN_PORT_WITH_DID: + case FSF_QTCB_CLOSE_PORT: + case FSF_QTCB_CLOSE_PHYSICAL_PORT: + len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx", + rec->data.port.wwpn); + len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", + rec->data.port.d_id); + len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x", + rec->data.port.port_handle); + break; + + case FSF_QTCB_OPEN_LUN: + case FSF_QTCB_CLOSE_LUN: + len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx", + rec->data.unit.wwpn); + len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx", + rec->data.unit.fcp_lun); + len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x", + rec->data.unit.port_handle); + len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x", + rec->data.unit.lun_handle); + break; + + case FSF_QTCB_SEND_ELS: + len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", + rec->data.send_els.d_id); + len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x", + rec->data.send_els.ls_code); + break; + + case FSF_QTCB_ABORT_FCP_CMND: + case FSF_QTCB_SEND_GENERIC: + case FSF_QTCB_EXCHANGE_CONFIG_DATA: + case FSF_QTCB_EXCHANGE_PORT_DATA: + case FSF_QTCB_DOWNLOAD_CONTROL_FILE: + case FSF_QTCB_UPLOAD_CONTROL_FILE: + break; + } + + return len; +} + +static inline int +zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) +{ + int len = 0; + + len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed); + len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x", + rec->status_type); + len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x", + rec->status_subtype); + len += zfcp_dbf_view_dump(out_buf + len, "queue_designator", + (char *)&rec->queue_designator, + sizeof(struct fsf_queue_designator), + 0, sizeof(struct fsf_queue_designator)); + len += zfcp_dbf_view_dump(out_buf + len, "payload", + (char *)&rec->payload, + rec->payload_size, 0, rec->payload_size); + + return len; +} + +static inline int +zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec) +{ + int len = 0; + + len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status); + len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x", + rec->qdio_error); + len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x", + rec->siga_error); + len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x", + rec->sbal_index); + len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x", + rec->sbal_count); + + return len; +} + +static int +zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf) +{ + struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf; + int len = 0; + + if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) + return 0; + + len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); + if (isalpha(rec->tag2[0])) + len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2); + if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0) + len += zfcp_hba_dbf_view_response(out_buf + len, + &rec->type.response); + else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0) + len += zfcp_hba_dbf_view_status(out_buf + len, + &rec->type.status); + else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) + len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio); + + len += sprintf(out_buf + len, "\n"); + + return len; +} + +struct debug_view zfcp_hba_dbf_view = { + "structured", + NULL, + &zfcp_dbf_view_header, + &zfcp_hba_dbf_view_format, + NULL, + NULL +}; + +inline void +_zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, + fc_id_t s_id, fc_id_t d_id, + void *buffer, int buflen) +{ + struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data; + struct zfcp_port *port = send_ct->port; + struct zfcp_adapter *adapter = port->adapter; + struct ct_hdr *header = (struct ct_hdr *)buffer; + struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf; + struct zfcp_san_dbf_record_ct *ct = &rec->type.ct; + unsigned long flags; + + spin_lock_irqsave(&adapter->san_dbf_lock, flags); + memset(rec, 0, sizeof(struct zfcp_san_dbf_record)); + strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); + rec->fsf_reqid = (unsigned long)fsf_req; + rec->fsf_seqno = fsf_req->seq_no; + rec->s_id = s_id; + rec->d_id = d_id; + if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { + ct->type.request.cmd_req_code = header->cmd_rsp_code; + ct->type.request.revision = header->revision; + ct->type.request.gs_type = header->gs_type; + ct->type.request.gs_subtype = header->gs_subtype; + ct->type.request.options = header->options; + ct->type.request.max_res_size = header->max_res_size; + } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { + ct->type.response.cmd_rsp_code = header->cmd_rsp_code; + ct->type.response.revision = header->revision; + ct->type.response.reason_code = header->reason_code; + ct->type.response.reason_code_expl = header->reason_code_expl; + ct->type.response.vendor_unique = header->vendor_unique; + } + ct->payload_size = + min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD); + memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size); + debug_event(adapter->san_dbf, 3, + rec, sizeof(struct zfcp_san_dbf_record)); + spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); +} + +inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; + struct zfcp_port *port = ct->port; + struct zfcp_adapter *adapter = port->adapter; + + _zfcp_san_dbf_event_common_ct("octc", + fsf_req, adapter->s_id, port->d_id, + zfcp_sg_to_address(ct->req), + ct->req->length); +} + +inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; + struct zfcp_port *port = ct->port; + struct zfcp_adapter *adapter = port->adapter; + + _zfcp_san_dbf_event_common_ct("rctc", + fsf_req, port->d_id, adapter->s_id, + zfcp_sg_to_address(ct->resp), + ct->resp->length); +} + +static inline void +_zfcp_san_dbf_event_common_els(const char *tag, int level, + struct zfcp_fsf_req *fsf_req, + fc_id_t s_id, fc_id_t d_id, u8 ls_code, + void *buffer, int buflen) +{ + struct zfcp_adapter *adapter = fsf_req->adapter; + struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf; + struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; + unsigned long flags; + int offset = 0; + + spin_lock_irqsave(&adapter->san_dbf_lock, flags); + do { + memset(rec, 0, sizeof(struct zfcp_san_dbf_record)); + if (offset == 0) { + strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); + rec->fsf_reqid = (unsigned long)fsf_req; + rec->fsf_seqno = fsf_req->seq_no; + rec->s_id = s_id; + rec->d_id = d_id; + rec->type.els.ls_code = ls_code; + buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD); + rec->type.els.payload_size = buflen; + memcpy(rec->type.els.payload, + buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD)); + offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD); + } else { + strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); + dump->total_size = buflen; + dump->offset = offset; + dump->size = min(buflen - offset, + (int)sizeof(struct zfcp_san_dbf_record) + - (int)sizeof(struct zfcp_dbf_dump)); + memcpy(dump->data, buffer + offset, dump->size); + offset += dump->size; + } + debug_event(adapter->san_dbf, level, + rec, sizeof(struct zfcp_san_dbf_record)); + } while (offset < buflen); + spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); +} + +inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; + + _zfcp_san_dbf_event_common_els("oels", 2, + fsf_req, els->adapter->s_id, els->d_id, + *(u8 *) zfcp_sg_to_address(els->req), + zfcp_sg_to_address(els->req), + els->req->length); +} + +inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; + + _zfcp_san_dbf_event_common_els("rels", 2, + fsf_req, els->d_id, els->adapter->s_id, + *(u8 *) zfcp_sg_to_address(els->req), + zfcp_sg_to_address(els->resp), + els->resp->length); +} + +inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_status_read_buffer *status_buffer = + (struct fsf_status_read_buffer *)fsf_req->data; + int length = (int)status_buffer->length - + (int)((void *)&status_buffer->payload - (void *)status_buffer); + + _zfcp_san_dbf_event_common_els("iels", 1, + fsf_req, status_buffer->d_id, + adapter->s_id, + *(u8 *) status_buffer->payload, + (void *)status_buffer->payload, length); +} + +static int +zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf) +{ + struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf; + char *buffer = NULL; + int buflen = 0, total = 0; + int len = 0; + + if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) + return 0; + + len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); + len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", + rec->fsf_reqid); + len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", + rec->fsf_seqno); + len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id); + len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id); + + if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x", + rec->type.ct.type.request.cmd_req_code); + len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x", + rec->type.ct.type.request.revision); + len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x", + rec->type.ct.type.request.gs_type); + len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x", + rec->type.ct.type.request.gs_subtype); + len += zfcp_dbf_view(out_buf + len, "options", "0x%02x", + rec->type.ct.type.request.options); + len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x", + rec->type.ct.type.request.max_res_size); + total = rec->type.ct.payload_size; + buffer = rec->type.ct.payload; + buflen = min(total, ZFCP_DBF_CT_PAYLOAD); + } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x", + rec->type.ct.type.response.cmd_rsp_code); + len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x", + rec->type.ct.type.response.revision); + len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x", + rec->type.ct.type.response.reason_code); + len += + zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x", + rec->type.ct.type.response.reason_code_expl); + len += + zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x", + rec->type.ct.type.response.vendor_unique); + total = rec->type.ct.payload_size; + buffer = rec->type.ct.payload; + buflen = min(total, ZFCP_DBF_CT_PAYLOAD); + } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || + strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || + strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x", + rec->type.els.ls_code); + total = rec->type.els.payload_size; + buffer = rec->type.els.payload; + buflen = min(total, ZFCP_DBF_ELS_PAYLOAD); + } + + len += zfcp_dbf_view_dump(out_buf + len, "payload", + buffer, buflen, 0, total); + + if (buflen == total) + len += sprintf(out_buf + len, "\n"); + + return len; +} + +struct debug_view zfcp_san_dbf_view = { + "structured", + NULL, + &zfcp_dbf_view_header, + &zfcp_san_dbf_view_format, + NULL, + NULL +}; + +static inline void +_zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, + struct zfcp_adapter *adapter, + struct scsi_cmnd *scsi_cmnd, + struct zfcp_fsf_req *new_fsf_req) +{ + struct zfcp_fsf_req *fsf_req = + (struct zfcp_fsf_req *)scsi_cmnd->host_scribble; + struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; + struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; + unsigned long flags; + struct fcp_rsp_iu *fcp_rsp; + char *fcp_rsp_info = NULL, *fcp_sns_info = NULL; + int offset = 0, buflen = 0; + + spin_lock_irqsave(&adapter->scsi_dbf_lock, flags); + do { + memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record)); + if (offset == 0) { + strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); + strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); + if (scsi_cmnd->device) { + rec->scsi_id = scsi_cmnd->device->id; + rec->scsi_lun = scsi_cmnd->device->lun; + } + rec->scsi_result = scsi_cmnd->result; + rec->scsi_cmnd = (unsigned long)scsi_cmnd; + rec->scsi_serial = scsi_cmnd->serial_number; + memcpy(rec->scsi_opcode, + &scsi_cmnd->cmnd, + min((int)scsi_cmnd->cmd_len, + ZFCP_DBF_SCSI_OPCODE)); + rec->scsi_retries = scsi_cmnd->retries; + rec->scsi_allowed = scsi_cmnd->allowed; + if (fsf_req != NULL) { + fcp_rsp = (struct fcp_rsp_iu *) + &(fsf_req->qtcb->bottom.io.fcp_rsp); + fcp_rsp_info = + zfcp_get_fcp_rsp_info_ptr(fcp_rsp); + fcp_sns_info = + zfcp_get_fcp_sns_info_ptr(fcp_rsp); + + rec->type.fcp.rsp_validity = + fcp_rsp->validity.value; + rec->type.fcp.rsp_scsi_status = + fcp_rsp->scsi_status; + rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid; + if (fcp_rsp->validity.bits.fcp_rsp_len_valid) + rec->type.fcp.rsp_code = + *(fcp_rsp_info + 3); + if (fcp_rsp->validity.bits.fcp_sns_len_valid) { + buflen = min((int)fcp_rsp->fcp_sns_len, + ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO); + rec->type.fcp.sns_info_len = buflen; + memcpy(rec->type.fcp.sns_info, + fcp_sns_info, + min(buflen, + ZFCP_DBF_SCSI_FCP_SNS_INFO)); + offset += min(buflen, + ZFCP_DBF_SCSI_FCP_SNS_INFO); + } + + rec->fsf_reqid = (unsigned long)fsf_req; + rec->fsf_seqno = fsf_req->seq_no; + rec->fsf_issued = fsf_req->issued; + } + if (new_fsf_req != NULL) { + rec->type.new_fsf_req.fsf_reqid = + (unsigned long) + new_fsf_req; + rec->type.new_fsf_req.fsf_seqno = + new_fsf_req->seq_no; + rec->type.new_fsf_req.fsf_issued = + new_fsf_req->issued; + } + } else { + strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); + dump->total_size = buflen; + dump->offset = offset; + dump->size = min(buflen - offset, + (int)sizeof(struct + zfcp_scsi_dbf_record) - + (int)sizeof(struct zfcp_dbf_dump)); + memcpy(dump->data, fcp_sns_info + offset, dump->size); + offset += dump->size; + } + debug_event(adapter->scsi_dbf, level, + rec, sizeof(struct zfcp_scsi_dbf_record)); + } while (offset < buflen); + spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags); +} + +inline void +zfcp_scsi_dbf_event_result(const char *tag, int level, + struct zfcp_adapter *adapter, + struct scsi_cmnd *scsi_cmnd) +{ + _zfcp_scsi_dbf_event_common("rslt", + tag, level, adapter, scsi_cmnd, NULL); +} + +inline void +zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, + struct scsi_cmnd *scsi_cmnd, + struct zfcp_fsf_req *new_fsf_req) +{ + _zfcp_scsi_dbf_event_common("abrt", + tag, 1, adapter, scsi_cmnd, new_fsf_req); +} + +inline void +zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, + struct scsi_cmnd *scsi_cmnd) +{ + struct zfcp_adapter *adapter = unit->port->adapter; + + _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", + tag, 1, adapter, scsi_cmnd, NULL); +} + +static int +zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, + char *out_buf, const char *in_buf) +{ + struct zfcp_scsi_dbf_record *rec = + (struct zfcp_scsi_dbf_record *)in_buf; + int len = 0; + + if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) + return 0; + + len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); + len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2); + len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id); + len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x", + rec->scsi_lun); + len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x", + rec->scsi_result); + len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx", + rec->scsi_cmnd); + len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx", + rec->scsi_serial); + len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode", + rec->scsi_opcode, + ZFCP_DBF_SCSI_OPCODE, + 0, ZFCP_DBF_SCSI_OPCODE); + len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x", + rec->scsi_retries); + len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x", + rec->scsi_allowed); + len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", + rec->fsf_reqid); + len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", + rec->fsf_seqno); + len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued); + if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) { + len += + zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x", + rec->type.fcp.rsp_validity); + len += + zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status", + "0x%02x", rec->type.fcp.rsp_scsi_status); + len += + zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x", + rec->type.fcp.rsp_resid); + len += + zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x", + rec->type.fcp.rsp_code); + len += + zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x", + rec->type.fcp.sns_info_len); + len += + zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info", + rec->type.fcp.sns_info, + min((int)rec->type.fcp.sns_info_len, + ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, + rec->type.fcp.sns_info_len); + } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { + len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx", + rec->type.new_fsf_req.fsf_reqid); + len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x", + rec->type.new_fsf_req.fsf_seqno); + len += zfcp_dbf_stck(out_buf + len, "fsf_issued", + rec->type.new_fsf_req.fsf_issued); + } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) || + (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) { + len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx", + rec->type.new_fsf_req.fsf_reqid); + len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x", + rec->type.new_fsf_req.fsf_seqno); + len += zfcp_dbf_stck(out_buf + len, "fsf_issued", + rec->type.new_fsf_req.fsf_issued); + } + + len += sprintf(out_buf + len, "\n"); + + return len; +} + +struct debug_view zfcp_scsi_dbf_view = { + "structured", + NULL, + &zfcp_dbf_view_header, + &zfcp_scsi_dbf_view_format, + NULL, + NULL +}; + +/** + * zfcp_adapter_debug_register - registers debug feature for an adapter + * @adapter: pointer to adapter for which debug features should be registered + * return: -ENOMEM on error, 0 otherwise + */ +int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) +{ + char dbf_name[DEBUG_MAX_NAME_LEN]; + + /* debug feature area which records recovery activity */ + spin_lock_init(&adapter->erp_dbf_lock); + sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); + adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, + sizeof(struct zfcp_erp_dbf_record)); + if (!adapter->erp_dbf) + goto failed; + debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); + debug_set_level(adapter->erp_dbf, 3); + + /* debug feature area which records HBA (FSF and QDIO) conditions */ + spin_lock_init(&adapter->hba_dbf_lock); + sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); + adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, + sizeof(struct zfcp_hba_dbf_record)); + if (!adapter->hba_dbf) + goto failed; + debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view); + debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view); + debug_set_level(adapter->hba_dbf, 3); + + /* debug feature area which records SAN command failures and recovery */ + spin_lock_init(&adapter->san_dbf_lock); + sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); + adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, + sizeof(struct zfcp_san_dbf_record)); + if (!adapter->san_dbf) + goto failed; + debug_register_view(adapter->san_dbf, &debug_hex_ascii_view); + debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view); + debug_set_level(adapter->san_dbf, 6); + + /* debug feature area which records SCSI command failures and recovery */ + spin_lock_init(&adapter->scsi_dbf_lock); + sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); + adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, + sizeof(struct zfcp_scsi_dbf_record)); + if (!adapter->scsi_dbf) + goto failed; + debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view); + debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view); + debug_set_level(adapter->scsi_dbf, 3); + + return 0; + + failed: + zfcp_adapter_debug_unregister(adapter); + + return -ENOMEM; +} + +/** + * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter + * @adapter: pointer to adapter for which debug features should be unregistered + */ +void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) +{ + debug_unregister(adapter->scsi_dbf); + debug_unregister(adapter->san_dbf); + debug_unregister(adapter->hba_dbf); + debug_unregister(adapter->erp_dbf); + adapter->scsi_dbf = NULL; + adapter->san_dbf = NULL; + adapter->hba_dbf = NULL; + adapter->erp_dbf = NULL; +} + +#undef ZFCP_LOG_AREA diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9160e68..fc5bb6f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -66,7 +66,7 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.3.0" +#define ZFCP_VERSION "4.4.0" /** * zfcp_sg_to_address - determine kernel address from struct scatterlist @@ -281,6 +281,171 @@ struct fcp_logo { } __attribute__((packed)); /* + * DBF stuff + */ +#define ZFCP_DBF_TAG_SIZE 4 + +struct zfcp_dbf_dump { + u8 tag[ZFCP_DBF_TAG_SIZE]; + u32 total_size; /* size of total dump data */ + u32 offset; /* how much data has being already dumped */ + u32 size; /* how much data comes with this record */ + u8 data[]; /* dump data */ +} __attribute__ ((packed)); + +/* FIXME: to be inflated when reworking the erp dbf */ +struct zfcp_erp_dbf_record { + u8 dummy[16]; +} __attribute__ ((packed)); + +struct zfcp_hba_dbf_record_response { + u32 fsf_command; + u64 fsf_reqid; + u32 fsf_seqno; + u64 fsf_issued; + u32 fsf_prot_status; + u32 fsf_status; + u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; + u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; + u32 fsf_req_status; + u8 sbal_first; + u8 sbal_curr; + u8 sbal_last; + u8 pool; + u64 erp_action; + union { + struct { + u64 scsi_cmnd; + u64 scsi_serial; + } send_fcp; + struct { + u64 wwpn; + u32 d_id; + u32 port_handle; + } port; + struct { + u64 wwpn; + u64 fcp_lun; + u32 port_handle; + u32 lun_handle; + } unit; + struct { + u32 d_id; + u8 ls_code; + } send_els; + } data; +} __attribute__ ((packed)); + +struct zfcp_hba_dbf_record_status { + u8 failed; + u32 status_type; + u32 status_subtype; + struct fsf_queue_designator + queue_designator; + u32 payload_size; +#define ZFCP_DBF_UNSOL_PAYLOAD 80 +#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32 +#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56 +#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32) + u8 payload[ZFCP_DBF_UNSOL_PAYLOAD]; +} __attribute__ ((packed)); + +struct zfcp_hba_dbf_record_qdio { + u32 status; + u32 qdio_error; + u32 siga_error; + u8 sbal_index; + u8 sbal_count; +} __attribute__ ((packed)); + +struct zfcp_hba_dbf_record { + u8 tag[ZFCP_DBF_TAG_SIZE]; + u8 tag2[ZFCP_DBF_TAG_SIZE]; + union { + struct zfcp_hba_dbf_record_response response; + struct zfcp_hba_dbf_record_status status; + struct zfcp_hba_dbf_record_qdio qdio; + } type; +} __attribute__ ((packed)); + +struct zfcp_san_dbf_record_ct { + union { + struct { + u16 cmd_req_code; + u8 revision; + u8 gs_type; + u8 gs_subtype; + u8 options; + u16 max_res_size; + } request; + struct { + u16 cmd_rsp_code; + u8 revision; + u8 reason_code; + u8 reason_code_expl; + u8 vendor_unique; + } response; + } type; + u32 payload_size; +#define ZFCP_DBF_CT_PAYLOAD 24 + u8 payload[ZFCP_DBF_CT_PAYLOAD]; +} __attribute__ ((packed)); + +struct zfcp_san_dbf_record_els { + u8 ls_code; + u32 payload_size; +#define ZFCP_DBF_ELS_PAYLOAD 32 +#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024 + u8 payload[ZFCP_DBF_ELS_PAYLOAD]; +} __attribute__ ((packed)); + +struct zfcp_san_dbf_record { + u8 tag[ZFCP_DBF_TAG_SIZE]; + u64 fsf_reqid; + u32 fsf_seqno; + u32 s_id; + u32 d_id; + union { + struct zfcp_san_dbf_record_ct ct; + struct zfcp_san_dbf_record_els els; + } type; +} __attribute__ ((packed)); + +struct zfcp_scsi_dbf_record { + u8 tag[ZFCP_DBF_TAG_SIZE]; + u8 tag2[ZFCP_DBF_TAG_SIZE]; + u32 scsi_id; + u32 scsi_lun; + u32 scsi_result; + u64 scsi_cmnd; + u64 scsi_serial; +#define ZFCP_DBF_SCSI_OPCODE 16 + u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; + u8 scsi_retries; + u8 scsi_allowed; + u64 fsf_reqid; + u32 fsf_seqno; + u64 fsf_issued; + union { + struct { + u64 fsf_reqid; + u32 fsf_seqno; + u64 fsf_issued; + } new_fsf_req; + struct { + u8 rsp_validity; + u8 rsp_scsi_status; + u32 rsp_resid; + u8 rsp_code; +#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16 +#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256 + u32 sns_info_len; + u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO]; + } fcp; + } type; +} __attribute__ ((packed)); + +/* * FC-FS stuff */ #define R_A_TOV 10 /* seconds */ @@ -339,34 +504,6 @@ struct zfcp_rc_entry { */ #define ZFCP_CT_TIMEOUT (3 * R_A_TOV) - -/***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/ - -/* debug feature entries per adapter */ -#define ZFCP_ERP_DBF_INDEX 1 -#define ZFCP_ERP_DBF_AREAS 2 -#define ZFCP_ERP_DBF_LENGTH 16 -#define ZFCP_ERP_DBF_LEVEL 3 -#define ZFCP_ERP_DBF_NAME "zfcperp" - -#define ZFCP_CMD_DBF_INDEX 2 -#define ZFCP_CMD_DBF_AREAS 1 -#define ZFCP_CMD_DBF_LENGTH 8 -#define ZFCP_CMD_DBF_LEVEL 3 -#define ZFCP_CMD_DBF_NAME "zfcpcmd" - -#define ZFCP_ABORT_DBF_INDEX 2 -#define ZFCP_ABORT_DBF_AREAS 1 -#define ZFCP_ABORT_DBF_LENGTH 8 -#define ZFCP_ABORT_DBF_LEVEL 6 -#define ZFCP_ABORT_DBF_NAME "zfcpabt" - -#define ZFCP_IN_ELS_DBF_INDEX 2 -#define ZFCP_IN_ELS_DBF_AREAS 1 -#define ZFCP_IN_ELS_DBF_LENGTH 8 -#define ZFCP_IN_ELS_DBF_LEVEL 6 -#define ZFCP_IN_ELS_DBF_NAME "zfcpels" - /******************** LOGGING MACROS AND DEFINES *****************************/ /* @@ -823,11 +960,18 @@ struct zfcp_adapter { u32 erp_low_mem_count; /* nr of erp actions waiting for memory */ struct zfcp_port *nameserver_port; /* adapter's nameserver */ - debug_info_t *erp_dbf; /* S/390 debug features */ - debug_info_t *abort_dbf; - debug_info_t *in_els_dbf; - debug_info_t *cmd_dbf; - spinlock_t dbf_lock; + debug_info_t *erp_dbf; + debug_info_t *hba_dbf; + debug_info_t *san_dbf; /* debug feature areas */ + debug_info_t *scsi_dbf; + spinlock_t erp_dbf_lock; + spinlock_t hba_dbf_lock; + spinlock_t san_dbf_lock; + spinlock_t scsi_dbf_lock; + struct zfcp_erp_dbf_record erp_dbf_buf; + struct zfcp_hba_dbf_record hba_dbf_buf; + struct zfcp_san_dbf_record san_dbf_buf; + struct zfcp_scsi_dbf_record scsi_dbf_buf; struct zfcp_adapter_mempool pool; /* Adapter memory pools */ struct qdio_initialize qdio_init_data; /* for qdio_establish */ struct device generic_services; /* directory for WKA ports */ @@ -902,6 +1046,7 @@ struct zfcp_fsf_req { issued on behalf of erp */ mempool_t *pool; /* used if request was alloacted from emergency pool */ + unsigned long long issued; /* request sent time (STCK) */ struct zfcp_unit *unit; }; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c400e3b..104b742 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -181,9 +181,25 @@ extern void zfcp_erp_port_access_changed(struct zfcp_port *); extern void zfcp_erp_unit_access_changed(struct zfcp_unit *); /******************************** AUX ****************************************/ -extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *, - void *, int); -extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *); -extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *, - struct fsf_status_read_buffer *, int); +extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *); +extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *, + struct fsf_status_read_buffer *); +extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, + unsigned int, unsigned int, unsigned int, + int, int); + +extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *); +extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *); +extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *); +extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *); +extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *); + +extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *, + struct scsi_cmnd *); +extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, + struct scsi_cmnd *, + struct zfcp_fsf_req *); +extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, + struct scsi_cmnd *); + #endif /* ZFCP_EXT_H */ diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 929f6c9..80ab721 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -285,51 +285,51 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) { int retval = 0; struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_qtcb *qtcb = fsf_req->qtcb; + union fsf_prot_status_qual *prot_status_qual = + &qtcb->prefix.prot_status_qual; - ZFCP_LOG_DEBUG("QTCB is at %p\n", fsf_req->qtcb); + zfcp_hba_dbf_event_fsf_response(fsf_req); if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n", (unsigned long) fsf_req); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */ - zfcp_cmd_dbf_event_fsf("dismiss", fsf_req, NULL, 0); goto skip_protstatus; } /* log additional information provided by FSF (if any) */ - if (unlikely(fsf_req->qtcb->header.log_length)) { + if (unlikely(qtcb->header.log_length)) { /* do not trust them ;-) */ - if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) { + if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL ("bug: ULP (FSF logging) log data starts " "beyond end of packet header. Ignored. " "(start=%i, size=%li)\n", - fsf_req->qtcb->header.log_start, + qtcb->header.log_start, sizeof(struct fsf_qtcb)); goto forget_log; } - if ((size_t) (fsf_req->qtcb->header.log_start + - fsf_req->qtcb->header.log_length) + if ((size_t) (qtcb->header.log_start + qtcb->header.log_length) > sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " "beyond end of packet header. Ignored. " "(start=%i, length=%i, size=%li)\n", - fsf_req->qtcb->header.log_start, - fsf_req->qtcb->header.log_length, + qtcb->header.log_start, + qtcb->header.log_length, sizeof(struct fsf_qtcb)); goto forget_log; } ZFCP_LOG_TRACE("ULP log data: \n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (char *) fsf_req->qtcb + - fsf_req->qtcb->header.log_start, - fsf_req->qtcb->header.log_length); + (char *) qtcb + qtcb->header.log_start, + qtcb->header.log_length); } forget_log: /* evaluate FSF Protocol Status */ - switch (fsf_req->qtcb->prefix.prot_status) { + switch (qtcb->prefix.prot_status) { case FSF_PROT_GOOD: case FSF_PROT_FSF_STATUS_PRESENTED: @@ -340,14 +340,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) "microcode of version 0x%x, the device driver " "only supports 0x%x. Aborting.\n", zfcp_get_busid_by_adapter(adapter), - fsf_req->qtcb->prefix.prot_status_qual. - version_error.fsf_version, ZFCP_QTCB_VERSION); - /* stop operation for this adapter */ - debug_text_exception(adapter->erp_dbf, 0, "prot_ver_err"); + prot_status_qual->version_error.fsf_version, + ZFCP_QTCB_VERSION); zfcp_erp_adapter_shutdown(adapter, 0); - zfcp_cmd_dbf_event_fsf("qverserr", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -355,16 +350,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) ZFCP_LOG_NORMAL("bug: Sequence number mismatch between " "driver (0x%x) and adapter %s (0x%x). " "Restarting all operations on this adapter.\n", - fsf_req->qtcb->prefix.req_seq_no, + qtcb->prefix.req_seq_no, zfcp_get_busid_by_adapter(adapter), - fsf_req->qtcb->prefix.prot_status_qual. - sequence_error.exp_req_seq_no); - debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err"); - /* restart operation on this adapter */ + prot_status_qual->sequence_error.exp_req_seq_no); zfcp_erp_adapter_reopen(adapter, 0); - zfcp_cmd_dbf_event_fsf("seqnoerr", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -375,22 +364,14 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) "that used on adapter %s. " "Stopping all operations on this adapter.\n", zfcp_get_busid_by_adapter(adapter)); - debug_text_exception(adapter->erp_dbf, 0, "prot_unsup_qtcb"); zfcp_erp_adapter_shutdown(adapter, 0); - zfcp_cmd_dbf_event_fsf("unsqtcbt", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PROT_HOST_CONNECTION_INITIALIZING: - zfcp_cmd_dbf_event_fsf("hconinit", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, &(adapter->status)); - debug_text_event(adapter->erp_dbf, 3, "prot_con_init"); break; case FSF_PROT_DUPLICATE_REQUEST_ID: @@ -413,11 +394,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) fsf_req, zfcp_get_busid_by_adapter(adapter)); } - debug_text_exception(adapter->erp_dbf, 0, "prot_dup_id"); zfcp_erp_adapter_shutdown(adapter, 0); - zfcp_cmd_dbf_event_fsf("dupreqid", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -483,8 +460,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) break; case FSF_PROT_REEST_QUEUE: - debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue"); - ZFCP_LOG_INFO("The local link to adapter with " + ZFCP_LOG_NORMAL("The local link to adapter with " "%s was re-plugged. " "Re-starting operations on this adapter.\n", zfcp_get_busid_by_adapter(adapter)); @@ -495,9 +471,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED); - zfcp_cmd_dbf_event_fsf("reestque", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -507,12 +480,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) "Restarting all operations on this " "adapter.\n", zfcp_get_busid_by_adapter(adapter)); - debug_text_event(adapter->erp_dbf, 0, "prot_err_sta"); - /* restart operation on this adapter */ zfcp_erp_adapter_reopen(adapter, 0); - zfcp_cmd_dbf_event_fsf("proterrs", fsf_req, - &fsf_req->qtcb->prefix.prot_status_qual, - sizeof (union fsf_prot_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -524,11 +492,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) "Stopping all operations on this adapter. " "(debug info 0x%x).\n", zfcp_get_busid_by_adapter(adapter), - fsf_req->qtcb->prefix.prot_status); - debug_text_event(adapter->erp_dbf, 0, "prot_inval:"); - debug_exception(adapter->erp_dbf, 0, - &fsf_req->qtcb->prefix.prot_status, - sizeof (u32)); + qtcb->prefix.prot_status); zfcp_erp_adapter_shutdown(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -568,28 +532,18 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req) "(debug info 0x%x).\n", zfcp_get_busid_by_adapter(fsf_req->adapter), fsf_req->qtcb->header.fsf_command); - debug_text_exception(fsf_req->adapter->erp_dbf, 0, - "fsf_s_unknown"); zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); - zfcp_cmd_dbf_event_fsf("unknownc", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_FCP_RSP_AVAILABLE: ZFCP_LOG_DEBUG("FCP Sense data will be presented to the " "SCSI stack.\n"); - debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp"); break; case FSF_ADAPTER_STATUS_AVAILABLE: - debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus"); zfcp_fsf_fsfstatus_qual_eval(fsf_req); break; - - default: - break; } skip_fsfstatus: @@ -617,44 +571,28 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { case FSF_SQ_FCP_RSP_AVAILABLE: - debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp"); break; case FSF_SQ_RETRY_IF_POSSIBLE: /* The SCSI-stack may now issue retries or escalate */ - debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry"); - zfcp_cmd_dbf_event_fsf("sqretry", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_COMMAND_ABORTED: /* Carry the aborted state on to upper layer */ - debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort"); - zfcp_cmd_dbf_event_fsf("sqabort", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED; fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_NO_RECOM: - debug_text_exception(fsf_req->adapter->erp_dbf, 0, - "fsf_sq_no_rec"); ZFCP_LOG_NORMAL("bug: No recommendation could be given for a" "problem on the adapter %s " "Stopping all operations on this adapter. ", zfcp_get_busid_by_adapter(fsf_req->adapter)); zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); - zfcp_cmd_dbf_event_fsf("sqnrecom", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_ULP_PROGRAMMING_ERROR: ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " "(adapter %s)\n", zfcp_get_busid_by_adapter(fsf_req->adapter)); - debug_text_exception(fsf_req->adapter->erp_dbf, 0, - "fsf_sq_ulp_err"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: @@ -668,13 +606,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) &fsf_req->qtcb->header.fsf_status_qual, sizeof (union fsf_status_qual)); - debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); - debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], - sizeof (u32)); - zfcp_cmd_dbf_event_fsf("squndef", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; } @@ -696,11 +627,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) struct zfcp_adapter *adapter = fsf_req->adapter; int retval = 0; - if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { - ZFCP_LOG_TRACE("fsf_req=%p, QTCB=%p\n", fsf_req, fsf_req->qtcb); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb)); - } switch (fsf_req->fsf_command) { @@ -760,13 +686,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " "not supported by the adapter %s\n", - zfcp_get_busid_by_adapter(fsf_req->adapter)); + zfcp_get_busid_by_adapter(adapter)); if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command) ZFCP_LOG_NORMAL ("bug: Command issued by the device driver differs " "from the command returned by the adapter %s " "(debug info 0x%x, 0x%x).\n", - zfcp_get_busid_by_adapter(fsf_req->adapter), + zfcp_get_busid_by_adapter(adapter), fsf_req->fsf_command, fsf_req->qtcb->header.fsf_command); } @@ -774,8 +700,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) if (!erp_action) return retval; - debug_text_event(adapter->erp_dbf, 3, "a_frh"); - debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); zfcp_erp_async_handler(erp_action, 0); return retval; @@ -846,6 +770,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) failed_buf: zfcp_fsf_req_free(fsf_req); failed_req_create: + zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); out: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return retval; @@ -921,35 +846,30 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) (struct fsf_status_read_buffer *) fsf_req->data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { + zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); mempool_free(status_buffer, adapter->pool.data_status_read); zfcp_fsf_req_free(fsf_req); goto out; } + zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer); + switch (status_buffer->status_type) { case FSF_STATUS_READ_PORT_CLOSED: - debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:"); - debug_event(adapter->erp_dbf, 3, - &status_buffer->d_id, sizeof (u32)); zfcp_fsf_status_read_port_closed(fsf_req); break; case FSF_STATUS_READ_INCOMING_ELS: - debug_text_event(adapter->erp_dbf, 3, "unsol_els:"); zfcp_fsf_incoming_els(fsf_req); break; case FSF_STATUS_READ_SENSE_DATA_AVAIL: - debug_text_event(adapter->erp_dbf, 3, "unsol_sense:"); ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", zfcp_get_busid_by_adapter(adapter)); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer, - sizeof(struct fsf_status_read_buffer)); break; case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:"); ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer, @@ -980,35 +900,30 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_STATUS_READ_CFDC_UPDATED: - debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:"); - ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n", + ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); zfcp_erp_adapter_access_changed(adapter); break; case FSF_STATUS_READ_CFDC_HARDENED: - debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:"); switch (status_buffer->status_subtype) { case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: - ZFCP_LOG_INFO("CFDC of adapter %s saved on SE\n", + ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n", zfcp_get_busid_by_adapter(adapter)); break; case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: - ZFCP_LOG_INFO("CFDC of adapter %s has been copied " + ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied " "to the secondary SE\n", zfcp_get_busid_by_adapter(adapter)); break; default: - ZFCP_LOG_INFO("CFDC of adapter %s has been hardened\n", + ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n", zfcp_get_busid_by_adapter(adapter)); } break; default: - debug_text_event(adapter->erp_dbf, 0, "unsol_unknown:"); - debug_exception(adapter->erp_dbf, 0, - &status_buffer->status_type, sizeof (u32)); - ZFCP_LOG_NORMAL("bug: An unsolicited status packet of unknown " + ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " "type was received (debug info 0x%x)\n", status_buffer->status_type); ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", @@ -1418,6 +1333,8 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, fsf_req->qtcb->bottom.support.timeout = ct->timeout; fsf_req->data = (unsigned long) ct; + zfcp_san_dbf_event_ct_request(fsf_req); + /* start QDIO request for this FSF request */ ret = zfcp_fsf_req_send(fsf_req, ct->timer); if (ret) { @@ -1476,6 +1393,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) switch (header->fsf_status) { case FSF_GOOD: + zfcp_san_dbf_event_ct_response(fsf_req); retval = 0; break; @@ -1720,6 +1638,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + zfcp_san_dbf_event_els_request(fsf_req); + /* start QDIO request for this FSF request */ ret = zfcp_fsf_req_send(fsf_req, els->timer); if (ret) { @@ -1777,6 +1697,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) switch (header->fsf_status) { case FSF_GOOD: + zfcp_san_dbf_event_els_response(fsf_req); retval = 0; break; @@ -3309,9 +3230,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_phand_nv"); zfcp_erp_adapter_reopen(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("porthinv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3330,9 +3248,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lhand_nv"); zfcp_erp_port_reopen(unit->port, 0); - zfcp_cmd_dbf_event_fsf("lunhinv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3763,10 +3678,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_hand_mis"); zfcp_erp_adapter_reopen(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("handmism", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3787,10 +3698,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) debug_text_exception(fsf_req->adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("unsclass", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3809,10 +3716,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_fcp_lun_nv"); zfcp_erp_port_reopen(unit->port, 0); - zfcp_cmd_dbf_event_fsf("fluninv", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3851,10 +3754,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_dir_ind_nv"); zfcp_erp_adapter_shutdown(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("dirinv", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3870,10 +3769,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_cmd_len_nv"); zfcp_erp_adapter_shutdown(unit->port->adapter, 0); - zfcp_cmd_dbf_event_fsf("cleninv", - fsf_req, - &header->fsf_status_qual, - sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -4043,7 +3938,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) &fsf_req->qtcb-> bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); - zfcp_cmd_dbf_event_fsf("clenmis", fsf_req, NULL, 0); set_host_byte(&scpnt->result, DID_ERROR); goto skip_fsfstatus; case RSP_CODE_FIELD_INVALID: @@ -4062,7 +3956,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) (char *) &fsf_req->qtcb-> bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); set_host_byte(&scpnt->result, DID_ERROR); - zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0); goto skip_fsfstatus; case RSP_CODE_RO_MISMATCH: /* hardware bug */ @@ -4079,7 +3972,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) &fsf_req->qtcb-> bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); - zfcp_cmd_dbf_event_fsf("codemism", fsf_req, NULL, 0); set_host_byte(&scpnt->result, DID_ERROR); goto skip_fsfstatus; default: @@ -4096,7 +3988,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) &fsf_req->qtcb-> bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); - zfcp_cmd_dbf_event_fsf("undeffcp", fsf_req, NULL, 0); set_host_byte(&scpnt->result, DID_ERROR); goto skip_fsfstatus; } @@ -4158,19 +4049,17 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) skip_fsfstatus: ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); - zfcp_cmd_dbf_event_scsi("response", scpnt); + if (scpnt->result != 0) + zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt); + else if (scpnt->retries > 0) + zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt); + else + zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt); /* cleanup pointer (need this especially for abort) */ scpnt->host_scribble = NULL; - /* - * NOTE: - * according to the outcome of a discussion on linux-scsi we - * don't need to grab the io_request_lock here since we use - * the new eh - */ /* always call back */ - (scpnt->scsi_done) (scpnt); /* @@ -4563,15 +4452,16 @@ zfcp_fsf_req_sbal_check(unsigned long *flags, * set qtcb pointer in fsf_req and initialize QTCB */ static inline void -zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd) +zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) { if (likely(fsf_req->qtcb != NULL)) { + fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; - fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd]; + fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; - fsf_req->qtcb->header.fsf_command = fsf_cmd; + fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; } } @@ -4639,7 +4529,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, goto failed_fsf_req; } - zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd); + fsf_req->adapter = adapter; + fsf_req->fsf_command = fsf_cmd; + + zfcp_fsf_req_qtcb_init(fsf_req); /* initialize waitqueue which may be used to wait on this request completion */ @@ -4661,8 +4554,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, goto failed_sbals; } - fsf_req->adapter = adapter; /* pointer to "parent" adapter */ - fsf_req->fsf_command = fsf_cmd; + if (fsf_req->qtcb) { + fsf_req->seq_no = adapter->fsf_req_seq_no; + fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; + } fsf_req->sbal_number = 1; fsf_req->sbal_first = req_queue->free_index; fsf_req->sbal_curr = req_queue->free_index; @@ -4713,9 +4608,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) struct zfcp_adapter *adapter; struct zfcp_qdio_queue *req_queue; volatile struct qdio_buffer_element *sbale; + int inc_seq_no; int new_distance_from_int; unsigned long flags; - int inc_seq_no = 1; int retval = 0; adapter = fsf_req->adapter; @@ -4729,23 +4624,13 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, sbale[1].length); - /* set sequence counter in QTCB */ - if (likely(fsf_req->qtcb)) { - fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; - fsf_req->seq_no = adapter->fsf_req_seq_no; - ZFCP_LOG_TRACE("FSF request %p of adapter %s gets " - "FSF sequence counter value of %i\n", - fsf_req, - zfcp_get_busid_by_adapter(adapter), - fsf_req->qtcb->prefix.req_seq_no); - } else - inc_seq_no = 0; - /* put allocated FSF request at list tail */ spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); + inc_seq_no = (fsf_req->qtcb != NULL); + /* figure out expiration time of timeout and start timeout */ if (unlikely(timer)) { timer->expires += jiffies; @@ -4775,6 +4660,8 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); + fsf_req->issued = get_clock(); + retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); @@ -4813,15 +4700,11 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) * routines resulting in missing sequence counter values * otherwise, */ + /* Don't increase for unsolicited status */ - if (likely(inc_seq_no)) { + if (inc_seq_no) adapter->fsf_req_seq_no++; - ZFCP_LOG_TRACE - ("FSF sequence counter value of adapter %s " - "increased to %i\n", - zfcp_get_busid_by_adapter(adapter), - adapter->fsf_req_seq_no); - } + /* count FSF requests pending */ atomic_inc(&adapter->fsf_reqs_active); } diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 07140df..57ce070 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -116,6 +116,7 @@ #define FSF_INVALID_COMMAND_OPTION 0x000000E5 /* #define FSF_ERROR 0x000000FF */ +#define FSF_PROT_STATUS_QUAL_SIZE 16 #define FSF_STATUS_QUALIFIER_SIZE 16 /* FSF status qualifier, recommendations */ @@ -311,6 +312,7 @@ struct fsf_qual_locallink_error { } __attribute__ ((packed)); union fsf_prot_status_qual { + u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; struct fsf_qual_version_error version_error; struct fsf_qual_sequence_error sequence_error; struct fsf_qual_locallink_error locallink_error; @@ -331,6 +333,7 @@ union fsf_status_qual { u8 byte[FSF_STATUS_QUALIFIER_SIZE]; u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)]; u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; + u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)]; struct fsf_queue_designator fsf_queue_designator; } __attribute__ ((packed)); diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 24e16ec..d719f66 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -54,8 +54,7 @@ static inline int zfcp_qdio_sbals_from_buffer static qdio_handler_t zfcp_qdio_request_handler; static qdio_handler_t zfcp_qdio_response_handler; static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, - unsigned int, - unsigned int, unsigned int); + unsigned int, unsigned int, unsigned int, int, int); #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO @@ -214,22 +213,12 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter) * */ static inline int -zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, - unsigned int status, - unsigned int qdio_error, unsigned int siga_error) +zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, + unsigned int qdio_error, unsigned int siga_error, + int first_element, int elements_processed) { int retval = 0; - if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE)) { - if (status & QDIO_STATUS_INBOUND_INT) { - ZFCP_LOG_TRACE("status is" - " QDIO_STATUS_INBOUND_INT \n"); - } - if (status & QDIO_STATUS_OUTBOUND_INT) { - ZFCP_LOG_TRACE("status is" - " QDIO_STATUS_OUTBOUND_INT \n"); - } - } if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) { retval = -EIO; @@ -237,9 +226,10 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, "qdio_error=0x%x, siga_error=0x%x)\n", status, qdio_error, siga_error); - /* Restarting IO on the failed adapter from scratch */ - debug_text_event(adapter->erp_dbf, 1, "qdio_err"); + zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error, + first_element, elements_processed); /* + * Restarting IO on the failed adapter from scratch. * Since we have been using this adapter, it is save to assume * that it is not failed but recoverable. The card seems to * report link-up events by self-initiated queue shutdown. @@ -282,7 +272,8 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, first_element, elements_processed); if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, - siga_error))) + siga_error, first_element, + elements_processed))) goto out; /* * we stored address of struct zfcp_adapter data structure @@ -334,7 +325,8 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, queue = &adapter->response_queue; if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, - siga_error))) + siga_error, first_element, + elements_processed))) goto out; /* diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index eeb5152..c1403a2 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -44,7 +44,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); -static int zfcp_task_management_function(struct zfcp_unit *, u8); +static int zfcp_task_management_function(struct zfcp_unit *, u8, + struct scsi_cmnd *); static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, scsi_lun_t); @@ -242,7 +243,10 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) { set_host_byte(&scpnt->result, result); - zfcp_cmd_dbf_event_scsi("failing", scpnt); + if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) + zfcp_scsi_dbf_event_result("fail", 4, + (struct zfcp_adapter*) scpnt->device->host->hostdata[0], + scpnt); /* return directly */ scpnt->scsi_done(scpnt); } @@ -434,7 +438,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) struct zfcp_adapter *adapter; struct zfcp_unit *unit; int retval = SUCCESS; - struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; + struct zfcp_fsf_req *new_fsf_req = NULL; + struct zfcp_fsf_req *old_fsf_req; unsigned long flags; scsi_host = scpnt->device->host; @@ -457,11 +462,8 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; if (!old_fsf_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); - ZFCP_LOG_NORMAL("bug: no old fsf request found\n"); - ZFCP_LOG_NORMAL("scsi_cmnd:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) scpnt, sizeof (struct scsi_cmnd)); - retval = FAILED; + zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req); + retval = SUCCESS; goto out; } old_fsf_req->data = 0; @@ -473,25 +475,27 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, adapter, unit, 0); if (!new_fsf_req) { + ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); retval = FAILED; - ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd " - "failed\n"); goto out; } /* wait for completion of abort */ __wait_event(new_fsf_req->completion_wq, new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - zfcp_fsf_req_free(new_fsf_req); /* status should be valid since signals were not permitted */ if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { + zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req); retval = SUCCESS; } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { + zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req); retval = SUCCESS; } else { + zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req); retval = FAILED; } + zfcp_fsf_req_free(new_fsf_req); out: return retval; } @@ -525,8 +529,9 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) */ if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, &unit->status)) { - retval = - zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET); + retval = zfcp_task_management_function(unit, + FCP_LOGICAL_UNIT_RESET, + scpnt); if (retval) { ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); if (retval == -ENOTSUPP) @@ -542,7 +547,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) goto out; } } - retval = zfcp_task_management_function(unit, FCP_TARGET_RESET); + retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); if (retval) { ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); retval = FAILED; @@ -555,7 +560,8 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) } static int -zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) +zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, + struct scsi_cmnd *scpnt) { struct zfcp_adapter *adapter = unit->port->adapter; struct zfcp_fsf_req *fsf_req; @@ -569,6 +575,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) "failed for unit 0x%016Lx on port 0x%016Lx on " "adapter %s\n", unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_adapter(adapter)); + zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt); retval = -ENOMEM; goto out; } @@ -576,11 +583,17 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) __wait_event(fsf_req->completion_wq, fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - /* check completion status of task management function */ - if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) + /* + * check completion status of task management function + */ + if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { + zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); retval = -EIO; - else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) + } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) { + zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt); retval = -ENOTSUPP; + } else + zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt); zfcp_fsf_req_free(fsf_req); out: -- cgit v0.10.2 From aef4a983090fa590481a86d9690dc3fa6bb121fa Mon Sep 17 00:00:00 2001 From: Maxim Shchetynin Date: Tue, 13 Sep 2005 21:51:16 +0200 Subject: [SCSI] zfcp: provide support for NPIV N_Port ID Virtualization (NPIV) allows a single FCP port to appear as multiple, distinct ports providing separate port identification. NPIV is supported by FC HBAs on System z9. zfcp was adapted to support this new feature. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index fff1537..64d9b90 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -279,9 +279,18 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, break; case FSF_STATUS_READ_LINK_DOWN: - rec->type.status.payload_size = sizeof(u64); + switch (status_buffer->status_subtype) { + case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: + case FSF_STATUS_READ_SUB_FDISC_FAILED: + rec->type.status.payload_size = + sizeof(struct fsf_link_down_info); + } break; + case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: + rec->type.status.payload_size = + ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; + break; } memcpy(&rec->type.status.payload, &status_buffer->payload, rec->type.status.payload_size); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index fc5bb6f..4b6af8e0 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -66,7 +66,7 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.4.0" +#define ZFCP_VERSION "4.5.0" /** * zfcp_sg_to_address - determine kernel address from struct scatterlist @@ -154,6 +154,11 @@ typedef u32 scsi_lun_t; #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 +/* Retry 5 times every 2 second, then every minute */ +#define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5 +#define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200 +#define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000 + /* timeout value for "default timer" for fsf requests */ #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); @@ -638,6 +643,7 @@ do { \ #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 +#define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 #define ZFCP_STATUS_ADAPTER_SCSI_UP \ (ZFCP_STATUS_COMMON_UNBLOCKED | \ @@ -915,13 +921,16 @@ struct zfcp_adapter { wwn_t peer_wwnn; /* P2P peer WWNN */ wwn_t peer_wwpn; /* P2P peer WWPN */ fc_id_t peer_d_id; /* P2P peer D_ID */ + wwn_t physical_wwpn; /* WWPN of physical port */ + fc_id_t physical_s_id; /* local FC port ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u8 fc_service_class; u32 fc_topology; /* FC topology */ u32 fc_link_speed; /* FC interface speed */ u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; - u32 supported_features;/* of FCP channel */ + u32 adapter_features; /* FCP channel features */ + u32 connection_features; /* host connection features */ u32 hardware_version; /* of FCP channel */ u8 serial_number[32]; /* of hardware */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 376cb0f..c4a6799 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); +static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_fsf_statusread( struct zfcp_erp_action *); @@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) { - int retval; + int xconfig, xport; + + if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &erp_action->adapter->status)) { + zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); + atomic_set(&erp_action->adapter->erp_counter, 0); + return ZFCP_ERP_FAILED; + } - /* do 'exchange configuration data' */ - retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); - if (retval == ZFCP_ERP_FAILED) - return retval; + xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); + xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); + if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) + return ZFCP_ERP_FAILED; - /* start the desired number of Status Reads */ - retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); - return retval; + return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); } /* @@ -2350,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) return retval; } +static int +zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) +{ + int retval = ZFCP_ERP_SUCCEEDED; + int retries; + int sleep; + struct zfcp_adapter *adapter = erp_action->adapter; + + atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); + + for (retries = 0; ; retries++) { + ZFCP_LOG_DEBUG("Doing exchange port data\n"); + zfcp_erp_action_to_running(erp_action); + zfcp_erp_timeout_init(erp_action); + if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { + retval = ZFCP_ERP_FAILED; + debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); + ZFCP_LOG_INFO("error: initiation of exchange of " + "port data failed for adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + } + debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); + ZFCP_LOG_DEBUG("Xchange underway\n"); + + /* + * Why this works: + * Both the normal completion handler as well as the timeout + * handler will do an 'up' when the 'exchange port data' + * request completes or times out. Thus, the signal to go on + * won't be lost utilizing this semaphore. + * Furthermore, this 'adapter_reopen' action is + * guaranteed to be the only action being there (highest action + * which prevents other actions from being created). + * Resulting from that, the wake signal recognized here + * _must_ be the one belonging to the 'exchange port + * data' request. + */ + down(&adapter->erp_ready_sem); + if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { + ZFCP_LOG_INFO("error: exchange of port data " + "for adapter %s timed out\n", + zfcp_get_busid_by_adapter(adapter)); + break; + } + + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status)) + break; + + ZFCP_LOG_DEBUG("host connection still initialising... " + "waiting and retrying...\n"); + /* sleep a little bit before retry */ + sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? + ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : + ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; + msleep(jiffies_to_msecs(sleep)); + } + + if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status)) { + ZFCP_LOG_INFO("error: exchange of port data for " + "adapter %s failed\n", + zfcp_get_busid_by_adapter(adapter)); + retval = ZFCP_ERP_FAILED; + } + + return retval; +} + /* * function: * @@ -3599,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) struct zfcp_port *port; unsigned long flags; + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) + return; + debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); debug_event(adapter->erp_dbf, 3, &adapter->name, 8); diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 104b742..c378226 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -96,7 +96,8 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); -extern int zfcp_fsf_exchange_port_data(struct zfcp_adapter *, +extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *, + struct zfcp_adapter *, struct fsf_qtcb_bottom_port *); extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 80ab721..f994f45 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -59,6 +59,8 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *); static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); +static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, + struct fsf_link_down_info *); static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); @@ -375,87 +377,19 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) break; case FSF_PROT_DUPLICATE_REQUEST_ID: - if (fsf_req->qtcb) { ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " "to the adapter %s is ambiguous. " - "Stopping all operations on this " - "adapter.\n", - *(unsigned long long *) - (&fsf_req->qtcb->bottom.support. - req_handle), - zfcp_get_busid_by_adapter(adapter)); - } else { - ZFCP_LOG_NORMAL("bug: The request identifier %p " - "to the adapter %s is ambiguous. " - "Stopping all operations on this " - "adapter. " - "(bug: got this for an unsolicited " - "status read request)\n", - fsf_req, + "Stopping all operations on this adapter.\n", + *(unsigned long long*) + (&qtcb->bottom.support.req_handle), zfcp_get_busid_by_adapter(adapter)); - } zfcp_erp_adapter_shutdown(adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PROT_LINK_DOWN: - /* - * 'test and set' is not atomic here - - * it's ok as long as calls to our response queue handler - * (and thus execution of this code here) are serialized - * by the qdio module - */ - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status)) { - switch (fsf_req->qtcb->prefix.prot_status_qual. - locallink_error.code) { - case FSF_PSQ_LINK_NOLIGHT: - ZFCP_LOG_INFO("The local link to adapter %s " - "is down (no light detected).\n", - zfcp_get_busid_by_adapter( - adapter)); - break; - case FSF_PSQ_LINK_WRAPPLUG: - ZFCP_LOG_INFO("The local link to adapter %s " - "is down (wrap plug detected).\n", - zfcp_get_busid_by_adapter( - adapter)); - break; - case FSF_PSQ_LINK_NOFCP: - ZFCP_LOG_INFO("The local link to adapter %s " - "is down (adjacent node on " - "link does not support FCP).\n", - zfcp_get_busid_by_adapter( - adapter)); - break; - default: - ZFCP_LOG_INFO("The local link to adapter %s " - "is down " - "(warning: unknown reason " - "code).\n", - zfcp_get_busid_by_adapter( - adapter)); - break; - - } - /* - * Due to the 'erp failed' flag the adapter won't - * be recovered but will be just set to 'blocked' - * state. All subordinary devices will have state - * 'blocked' and 'erp failed', too. - * Thus the adapter is still able to provide - * 'link up' status without being flooded with - * requests. - * (note: even 'close port' is not permitted) - */ - ZFCP_LOG_INFO("Stopping all operations for adapter " - "%s.\n", - zfcp_get_busid_by_adapter(adapter)); - atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | - ZFCP_STATUS_COMMON_ERP_FAILED, - &adapter->status); - zfcp_erp_adapter_reopen(adapter, 0); - } + zfcp_fsf_link_down_info_eval(adapter, + &prot_status_qual->link_down_info); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -613,6 +547,110 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) return retval; } +/** + * zfcp_fsf_link_down_info_eval - evaluate link down information block + */ +static void +zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, + struct fsf_link_down_info *link_down) +{ + switch (link_down->error_code) { + case FSF_PSQ_LINK_NO_LIGHT: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(no light detected)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_WRAP_PLUG: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(wrap plug detected)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_NO_FCP: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(adjacent node on link does not support FCP)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_FIRMWARE_UPDATE: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(firmware update in progress)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_INVALID_WWPN: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(duplicate or invalid WWPN detected)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_NO_NPIV_SUPPORT: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(no support for NPIV by Fabric)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_NO_FCP_RESOURCES: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(out of resource in FCP daughtercard)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(out of resource in Fabric)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(unable to Fabric login)\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: + ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: + ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: + ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + default: + ZFCP_LOG_NORMAL("The local link to adapter %s is down " + "(warning: unknown reason code %d)\n", + zfcp_get_busid_by_adapter(adapter), + link_down->error_code); + } + + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) + ZFCP_LOG_DEBUG("Debug information to link down: " + "primary_status=0x%02x " + "ioerr_code=0x%02x " + "action_code=0x%02x " + "reason_code=0x%02x " + "explanation_code=0x%02x " + "vendor_specific_code=0x%02x\n", + link_down->primary_status, + link_down->ioerr_code, + link_down->action_code, + link_down->reason_code, + link_down->explanation_code, + link_down->vendor_specific_code); + + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status)) { + atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, + &adapter->status); + switch (link_down->error_code) { + case FSF_PSQ_LINK_NO_LIGHT: + case FSF_PSQ_LINK_WRAP_PLUG: + case FSF_PSQ_LINK_NO_FCP: + case FSF_PSQ_LINK_FIRMWARE_UPDATE: + zfcp_erp_adapter_reopen(adapter, 0); + break; + default: + zfcp_erp_adapter_failed(adapter); + } + } +} + /* * function: zfcp_fsf_req_dispatch * @@ -877,17 +915,32 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) break; case FSF_STATUS_READ_LINK_DOWN: - debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:"); - ZFCP_LOG_INFO("Local link to adapter %s is down\n", + switch (status_buffer->status_subtype) { + case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: + ZFCP_LOG_INFO("Physical link to adapter %s is down\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_STATUS_READ_SUB_FDISC_FAILED: + ZFCP_LOG_INFO("Local link to adapter %s is down " + "due to failed FDISC login\n", zfcp_get_busid_by_adapter(adapter)); - atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status); - zfcp_erp_adapter_failed(adapter); + break; + case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: + ZFCP_LOG_INFO("Local link to adapter %s is down " + "due to firmware update on adapter\n", + zfcp_get_busid_by_adapter(adapter)); + break; + default: + ZFCP_LOG_INFO("Local link to adapter %s is down " + "due to unknown reason\n", + zfcp_get_busid_by_adapter(adapter)); + }; + zfcp_fsf_link_down_info_eval(adapter, + (struct fsf_link_down_info *) &status_buffer->payload); break; case FSF_STATUS_READ_LINK_UP: - debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:"); - ZFCP_LOG_INFO("Local link to adapter %s was replugged. " + ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " "Restarting operations on this adapter\n", zfcp_get_busid_by_adapter(adapter)); /* All ports should be marked as ready to run again */ @@ -922,6 +975,16 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) } break; + case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: + debug_text_event(adapter->erp_dbf, 2, "unsol_features:"); + ZFCP_LOG_INFO("List of supported features on adapter %s has " + "been changed from 0x%08X to 0x%08X\n", + zfcp_get_busid_by_adapter(adapter), + *(u32*) (status_buffer->payload + 4), + *(u32*) (status_buffer->payload)); + adapter->adapter_features = *(u32*) status_buffer->payload; + break; + default: ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " "type was received (debug info 0x%x)\n", @@ -1281,7 +1344,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); sbale[3].length = ct->resp[0].length; sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; - } else if (adapter->supported_features & + } else if (adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS) { /* try to use chained SBALs */ bytes = zfcp_qdio_sbals_from_sg(fsf_req, @@ -1584,7 +1647,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); sbale[3].length = els->resp[0].length; sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; - } else if (adapter->supported_features & + } else if (adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS) { /* try to use chained SBALs */ bytes = zfcp_qdio_sbals_from_sg(fsf_req, @@ -1877,7 +1940,9 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) erp_action->fsf_req->erp_action = erp_action; erp_action->fsf_req->qtcb->bottom.config.feature_selection = - (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING); + FSF_FEATURE_CFDC | + FSF_FEATURE_LUN_SHARING | + FSF_FEATURE_UPDATE_ALERT; /* start QDIO request for this FSF request */ retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); @@ -1918,7 +1983,8 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", bottom->low_qtcb_version, bottom->high_qtcb_version); adapter->fsf_lic_version = bottom->lic_version; - adapter->supported_features = bottom->supported_features; + adapter->adapter_features = bottom->adapter_features; + adapter->connection_features = bottom->connection_features; adapter->peer_wwpn = 0; adapter->peer_wwnn = 0; adapter->peer_d_id = 0; @@ -1930,6 +1996,10 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) adapter->fc_topology = bottom->fc_topology; adapter->fc_link_speed = bottom->fc_link_speed; adapter->hydra_version = bottom->adapter_type; + if (adapter->physical_wwpn == 0) + adapter->physical_wwpn = adapter->wwpn; + if (adapter->physical_s_id == 0) + adapter->physical_s_id = adapter->s_id; } else { adapter->wwnn = 0; adapter->wwpn = 0; @@ -1945,7 +2015,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) adapter->peer_wwnn = bottom->plogi_payload.wwnn; } - if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ + if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { adapter->hardware_version = bottom->hardware_version; memcpy(adapter->serial_number, bottom->serial_number, 17); EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); @@ -2001,11 +2071,12 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) { struct fsf_qtcb_bottom_config *bottom; struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_qtcb *qtcb = fsf_req->qtcb; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) return -EIO; - switch (fsf_req->qtcb->header.fsf_status) { + switch (qtcb->header.fsf_status) { case FSF_GOOD: if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) @@ -2035,7 +2106,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; case FSF_TOPO_FABRIC: - ZFCP_LOG_INFO("Switched fabric fibrechannel " + ZFCP_LOG_NORMAL("Switched fabric fibrechannel " "network detected at adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); break; @@ -2053,7 +2124,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; } - bottom = &fsf_req->qtcb->bottom.config; + bottom = &qtcb->bottom.config; if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " "allowed by the adapter %s " @@ -2078,12 +2149,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) return -EIO; - ZFCP_LOG_INFO("Local link to adapter %s is down\n", - zfcp_get_busid_by_adapter(adapter)); - atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | - ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, - &adapter->status); - zfcp_erp_adapter_failed(adapter); + atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); + + zfcp_fsf_link_down_info_eval(adapter, + &qtcb->header.fsf_status_qual.link_down_info); break; default: debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); @@ -2097,11 +2166,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) /** * zfcp_fsf_exchange_port_data - request information about local port + * @erp_action: ERP action for the adapter for which port data is requested * @adapter: for which port data is requested * @data: response to exchange port data request */ int -zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, +zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, + struct zfcp_adapter *adapter, struct fsf_qtcb_bottom_port *data) { volatile struct qdio_buffer_element *sbale; @@ -2110,7 +2181,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, struct zfcp_fsf_req *fsf_req; struct timer_list *timer; - if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){ + if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { ZFCP_LOG_INFO("error: exchange port data " "command not supported by adapter %s\n", zfcp_get_busid_by_adapter(adapter)); @@ -2134,6 +2205,12 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, goto out; } + if (erp_action) { + erp_action->fsf_req = fsf_req; + fsf_req->erp_action = erp_action; + } + + if (data) fsf_req->data = (unsigned long) data; sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); @@ -2151,6 +2228,8 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, "command on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_req_free(fsf_req); + if (erp_action) + erp_action->fsf_req = NULL; write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); goto out; @@ -2179,23 +2258,40 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) { - struct fsf_qtcb_bottom_port *bottom; - struct fsf_qtcb_bottom_port *data; - - data = (struct fsf_qtcb_bottom_port*) fsf_req->data; + struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_qtcb *qtcb = fsf_req->qtcb; + struct fsf_qtcb_bottom_port *bottom, *data; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) return; - switch (fsf_req->qtcb->header.fsf_status) { + switch (qtcb->header.fsf_status) { case FSF_GOOD: - bottom = &fsf_req->qtcb->bottom.port; - memcpy(data, bottom, sizeof(*data)); + atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); + + bottom = &qtcb->bottom.port; + data = (struct fsf_qtcb_bottom_port*) fsf_req->data; + if (data) + memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); + if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { + adapter->physical_wwpn = bottom->wwpn; + adapter->physical_s_id = bottom->fc_port_id; + } else { + adapter->physical_wwpn = adapter->wwpn; + adapter->physical_s_id = adapter->s_id; + } + break; + + case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: + atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); + + zfcp_fsf_link_down_info_eval(adapter, + &qtcb->header.fsf_status_qual.link_down_info); break; default: - debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng"); - debug_event(fsf_req->adapter->erp_dbf, 0, + debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); + debug_event(adapter->erp_dbf, 0, &fsf_req->qtcb->header.fsf_status, sizeof(u32)); } } @@ -2629,7 +2725,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) &erp_action->port->status); /* save a pointer to this port */ erp_action->fsf_req->data = (unsigned long) erp_action->port; - /* port to be closeed */ + /* port to be closed */ erp_action->fsf_req->qtcb->header.port_handle = erp_action->port->handle; erp_action->fsf_req->erp_action = erp_action; @@ -2833,6 +2929,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) erp_action->port->handle; erp_action->fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun; + if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) erp_action->fsf_req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); @@ -2880,7 +2977,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) struct fsf_qtcb_bottom_support *bottom; struct fsf_queue_designator *queue_designator; u16 subtable, rule, counter; - u32 allowed, exclusive, readwrite; + int exclusive, readwrite; unit = (struct zfcp_unit *) fsf_req->data; @@ -2894,10 +2991,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) bottom = &fsf_req->qtcb->bottom.support; queue_designator = &header->fsf_status_qual.fsf_queue_designator; - allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED; - exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; - readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_UNIT_SHARED | ZFCP_STATUS_UNIT_READONLY, @@ -3071,10 +3164,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) unit->handle); /* mark unit as open */ atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); - atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | - ZFCP_STATUS_COMMON_ACCESS_BOXED, - &unit->status); - if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){ + + if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && + (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && + (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) { + exclusive = (bottom->lun_access_info & + FSF_UNIT_ACCESS_EXCLUSIVE); + readwrite = (bottom->lun_access_info & + FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); + if (!exclusive) atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status); @@ -4164,7 +4262,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, int direction; int retval = 0; - if (!(adapter->supported_features & FSF_FEATURE_CFDC)) { + if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) { ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", zfcp_get_busid_by_adapter(adapter)); retval = -EOPNOTSUPP; diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 57ce070..48719f0 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -140,9 +140,18 @@ #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 /* FSF status qualifier (most significant 4 bytes), local link down */ -#define FSF_PSQ_LINK_NOLIGHT 0x00000004 -#define FSF_PSQ_LINK_WRAPPLUG 0x00000008 -#define FSF_PSQ_LINK_NOFCP 0x00000010 +#define FSF_PSQ_LINK_NO_LIGHT 0x00000004 +#define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 +#define FSF_PSQ_LINK_NO_FCP 0x00000010 +#define FSF_PSQ_LINK_FIRMWARE_UPDATE 0x00000020 +#define FSF_PSQ_LINK_INVALID_WWPN 0x00000100 +#define FSF_PSQ_LINK_NO_NPIV_SUPPORT 0x00000200 +#define FSF_PSQ_LINK_NO_FCP_RESOURCES 0x00000400 +#define FSF_PSQ_LINK_NO_FABRIC_RESOURCES 0x00000800 +#define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE 0x00001000 +#define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000 +#define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000 +#define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000 /* payload size in status read buffer */ #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 @@ -155,15 +164,21 @@ #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 #define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 -#define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ +#define FSF_STATUS_READ_LINK_DOWN 0x00000005 #define FSF_STATUS_READ_LINK_UP 0x00000006 #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B +#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C /* status subtypes in status read buffer */ #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 +/* status subtypes for link down */ +#define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000 +#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 +#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 + /* status subtypes for CFDC */ #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F @@ -194,11 +209,15 @@ #define FSF_QTCB_LOG_SIZE 1024 /* channel features */ -#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 #define FSF_FEATURE_CFDC 0x00000002 #define FSF_FEATURE_LUN_SHARING 0x00000004 #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 +#define FSF_FEATURE_UPDATE_ALERT 0x00000100 + +/* host connection features */ +#define FSF_FEATURE_NPIV_MODE 0x00000001 +#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002 /* option */ #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 @@ -306,16 +325,23 @@ struct fsf_qual_sequence_error { u32 res1[3]; } __attribute__ ((packed)); -struct fsf_qual_locallink_error { - u32 code; - u32 res1[3]; +struct fsf_link_down_info { + u32 error_code; + u32 res1; + u8 res2[2]; + u8 primary_status; + u8 ioerr_code; + u8 action_code; + u8 reason_code; + u8 explanation_code; + u8 vendor_specific_code; } __attribute__ ((packed)); union fsf_prot_status_qual { u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; struct fsf_qual_version_error version_error; struct fsf_qual_sequence_error sequence_error; - struct fsf_qual_locallink_error locallink_error; + struct fsf_link_down_info link_down_info; } __attribute__ ((packed)); struct fsf_qtcb_prefix { @@ -335,6 +361,7 @@ union fsf_status_qual { u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)]; struct fsf_queue_designator fsf_queue_designator; + struct fsf_link_down_info link_down_info; } __attribute__ ((packed)); struct fsf_qtcb_header { @@ -409,8 +436,8 @@ struct fsf_qtcb_bottom_config { u32 low_qtcb_version; u32 max_qtcb_size; u32 max_data_transfer_size; - u32 supported_features; - u8 res1[4]; + u32 adapter_features; + u32 connection_features; u32 fc_topology; u32 fc_link_speed; u32 adapter_type; @@ -428,7 +455,7 @@ struct fsf_qtcb_bottom_config { } __attribute__ ((packed)); struct fsf_qtcb_bottom_port { - u8 res1[8]; + u64 wwpn; u32 fc_port_id; u32 port_type; u32 port_state; diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index e7345a7..c406ea5 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -68,6 +68,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); +ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); +ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); @@ -261,6 +263,8 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_peer_wwnn.attr, &dev_attr_peer_wwpn.attr, &dev_attr_peer_d_id.attr, + &dev_attr_physical_wwpn.attr, + &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, &dev_attr_fc_link_speed.attr, -- cgit v0.10.2 From 13e1e1f08c1c098c7574c1fa72bd8c67792dc89b Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 19 Sep 2005 16:56:17 +0200 Subject: [SCSI] zfcp: add additional fc_host attributes this patch adds some fc host attributes and removes its equivalents from the zfcp_adapter structure and zfcp specific sysfs subtree. Furthermore it removes superfluous calls to fc_remort_port_delete when an adapter is set offline because rports will be removed by fc_remove_host anyway. Signed-off-by: Andreas Herrmann Signed-off-by: James Bottomley diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index b30abab..0fc4638 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -202,19 +202,9 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) { struct zfcp_adapter *adapter; - struct zfcp_port *port; - struct fc_rport *rport; down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); - /* might be racy, but we cannot take config_lock due to the fact that - fc_remote_port_delete might sleep */ - list_for_each_entry(port, &adapter->port_list_head, list) - if (port->rport) { - rport = port->rport; - port->rport = NULL; - fc_remote_port_delete(rport); - } zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_wait(adapter); zfcp_adapter_scsi_unregister(adapter); diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 64d9b90..826fb3b 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -486,8 +486,7 @@ struct debug_view zfcp_hba_dbf_view = { inline void _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, - fc_id_t s_id, fc_id_t d_id, - void *buffer, int buflen) + u32 s_id, u32 d_id, void *buffer, int buflen) { struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data; struct zfcp_port *port = send_ct->port; @@ -532,9 +531,9 @@ inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) struct zfcp_port *port = ct->port; struct zfcp_adapter *adapter = port->adapter; - _zfcp_san_dbf_event_common_ct("octc", - fsf_req, adapter->s_id, port->d_id, - zfcp_sg_to_address(ct->req), + _zfcp_san_dbf_event_common_ct("octc", fsf_req, + fc_host_port_id(adapter->scsi_host), + port->d_id, zfcp_sg_to_address(ct->req), ct->req->length); } @@ -544,17 +543,16 @@ inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) struct zfcp_port *port = ct->port; struct zfcp_adapter *adapter = port->adapter; - _zfcp_san_dbf_event_common_ct("rctc", - fsf_req, port->d_id, adapter->s_id, + _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id, + fc_host_port_id(adapter->scsi_host), zfcp_sg_to_address(ct->resp), ct->resp->length); } static inline void _zfcp_san_dbf_event_common_els(const char *tag, int level, - struct zfcp_fsf_req *fsf_req, - fc_id_t s_id, fc_id_t d_id, u8 ls_code, - void *buffer, int buflen) + struct zfcp_fsf_req *fsf_req, u32 s_id, + u32 d_id, u8 ls_code, void *buffer, int buflen) { struct zfcp_adapter *adapter = fsf_req->adapter; struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf; @@ -597,8 +595,9 @@ inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; - _zfcp_san_dbf_event_common_els("oels", 2, - fsf_req, els->adapter->s_id, els->d_id, + _zfcp_san_dbf_event_common_els("oels", 2, fsf_req, + fc_host_port_id(els->adapter->scsi_host), + els->d_id, *(u8 *) zfcp_sg_to_address(els->req), zfcp_sg_to_address(els->req), els->req->length); @@ -608,8 +607,8 @@ inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) { struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; - _zfcp_san_dbf_event_common_els("rels", 2, - fsf_req, els->d_id, els->adapter->s_id, + _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id, + fc_host_port_id(els->adapter->scsi_host), *(u8 *) zfcp_sg_to_address(els->req), zfcp_sg_to_address(els->resp), els->resp->length); @@ -623,9 +622,8 @@ inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) int length = (int)status_buffer->length - (int)((void *)&status_buffer->payload - (void *)status_buffer); - _zfcp_san_dbf_event_common_els("iels", 1, - fsf_req, status_buffer->d_id, - adapter->s_id, + _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id, + fc_host_port_id(adapter->scsi_host), *(u8 *) status_buffer->payload, (void *)status_buffer->payload, length); } diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 4b6af8e0..d81b737 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -165,7 +165,6 @@ typedef u32 scsi_lun_t; /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ typedef unsigned long long wwn_t; -typedef unsigned int fc_id_t; typedef unsigned long long fcp_lun_t; /* data length field may be at variable position in FCP-2 FCP_CMND IU */ typedef unsigned int fcp_dl_t; @@ -806,7 +805,7 @@ struct ct_iu_gid_pn_req { /* FS_ACC IU and data unit for GID_PN nameserver request */ struct ct_iu_gid_pn_resp { struct ct_hdr header; - fc_id_t d_id; + u32 d_id; } __attribute__ ((packed)); typedef void (*zfcp_send_ct_handler_t)(unsigned long); @@ -872,7 +871,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); struct zfcp_send_els { struct zfcp_adapter *adapter; struct zfcp_port *port; - fc_id_t d_id; + u32 d_id; struct scatterlist *req; struct scatterlist *resp; unsigned int req_count; @@ -915,24 +914,19 @@ struct zfcp_adapter { atomic_t refcount; /* reference count */ wait_queue_head_t remove_wq; /* can be used to wait for refcount drop to zero */ - wwn_t wwnn; /* WWNN */ - wwn_t wwpn; /* WWPN */ - fc_id_t s_id; /* N_Port ID */ wwn_t peer_wwnn; /* P2P peer WWNN */ wwn_t peer_wwpn; /* P2P peer WWPN */ - fc_id_t peer_d_id; /* P2P peer D_ID */ + u32 peer_d_id; /* P2P peer D_ID */ wwn_t physical_wwpn; /* WWPN of physical port */ - fc_id_t physical_s_id; /* local FC port ID */ + u32 physical_s_id; /* local FC port ID */ struct ccw_device *ccw_device; /* S/390 ccw device */ u8 fc_service_class; u32 fc_topology; /* FC topology */ - u32 fc_link_speed; /* FC interface speed */ u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; u32 adapter_features; /* FCP channel features */ u32 connection_features; /* host connection features */ u32 hardware_version; /* of FCP channel */ - u8 serial_number[32]; /* of hardware */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ unsigned short scsi_host_no; /* Assigned host number */ unsigned char name[9]; @@ -1006,7 +1000,7 @@ struct zfcp_port { atomic_t status; /* status of this remote port */ wwn_t wwnn; /* WWNN if known */ wwn_t wwpn; /* WWPN */ - fc_id_t d_id; /* D_ID */ + u32 d_id; /* D_ID */ u32 handle; /* handle assigned by FSF */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c4a6799..023f4e5 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -346,13 +346,13 @@ zfcp_erp_adisc(struct zfcp_port *port) /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports without FC-AL-2 capability, so we don't set it */ - adisc->wwpn = adapter->wwpn; - adisc->wwnn = adapter->wwnn; - adisc->nport_id = adapter->s_id; + adisc->wwpn = fc_host_port_name(adapter->scsi_host); + adisc->wwnn = fc_host_node_name(adapter->scsi_host); + adisc->nport_id = fc_host_port_id(adapter->scsi_host); ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " "(wwpn=0x%016Lx, wwnn=0x%016Lx, " "hard_nport_id=0x%08x, nport_id=0x%08x)\n", - adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn, + adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, adisc->hard_nport_id, adisc->nport_id); @@ -405,7 +405,7 @@ zfcp_erp_adisc_handler(unsigned long data) struct zfcp_send_els *send_els; struct zfcp_port *port; struct zfcp_adapter *adapter; - fc_id_t d_id; + u32 d_id; struct zfcp_ls_adisc_acc *adisc; send_els = (struct zfcp_send_els *) data; @@ -436,9 +436,9 @@ zfcp_erp_adisc_handler(unsigned long data) ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " "hard_nport_id=0x%08x, nport_id=0x%08x)\n", - d_id, adapter->s_id, (wwn_t) adisc->wwpn, - (wwn_t) adisc->wwnn, adisc->hard_nport_id, - adisc->nport_id); + d_id, fc_host_port_id(adapter->scsi_host), + (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, + adisc->hard_nport_id, adisc->nport_id); /* set wwnn for port */ if (port->wwnn == 0) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index f994f45..3b0fc11 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1617,7 +1617,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) { volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; - fc_id_t d_id; + u32 d_id; struct zfcp_adapter *adapter; unsigned long lock_flags; int bytes; @@ -1740,7 +1740,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) { struct zfcp_adapter *adapter; struct zfcp_port *port; - fc_id_t d_id; + u32 d_id; struct fsf_qtcb_header *header; struct fsf_qtcb_bottom_support *bottom; struct zfcp_send_els *send_els; @@ -1978,6 +1978,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) { struct fsf_qtcb_bottom_config *bottom; struct zfcp_adapter *adapter = fsf_req->adapter; + struct Scsi_Host *shost = adapter->scsi_host; bottom = &fsf_req->qtcb->bottom.config; ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", @@ -1990,22 +1991,23 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) adapter->peer_d_id = 0; if (xchg_ok) { - adapter->wwnn = bottom->nport_serv_param.wwnn; - adapter->wwpn = bottom->nport_serv_param.wwpn; - adapter->s_id = bottom->s_id & ZFCP_DID_MASK; + fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; + fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; + fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; + fc_host_speed(shost) = bottom->fc_link_speed; + fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; adapter->fc_topology = bottom->fc_topology; - adapter->fc_link_speed = bottom->fc_link_speed; adapter->hydra_version = bottom->adapter_type; if (adapter->physical_wwpn == 0) - adapter->physical_wwpn = adapter->wwpn; + adapter->physical_wwpn = fc_host_port_name(shost); if (adapter->physical_s_id == 0) - adapter->physical_s_id = adapter->s_id; + adapter->physical_s_id = fc_host_port_id(shost); } else { - adapter->wwnn = 0; - adapter->wwpn = 0; - adapter->s_id = 0; + fc_host_node_name(shost) = 0; + fc_host_port_name(shost) = 0; + fc_host_port_id(shost) = 0; + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; adapter->fc_topology = 0; - adapter->fc_link_speed = 0; adapter->hydra_version = 0; } @@ -2017,24 +2019,26 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { adapter->hardware_version = bottom->hardware_version; - memcpy(adapter->serial_number, bottom->serial_number, 17); - EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); + memcpy(fc_host_serial_number(shost), bottom->serial_number, + min(FC_SERIAL_NUMBER_SIZE, 17)); + EBCASC(fc_host_serial_number(shost), + min(FC_SERIAL_NUMBER_SIZE, 17)); } ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" - "WWNN 0x%016Lx, " - "WWPN 0x%016Lx, " - "S_ID 0x%08x,\n" - "adapter version 0x%x, " - "LIC version 0x%x, " - "FC link speed %d Gb/s\n", - zfcp_get_busid_by_adapter(adapter), - adapter->wwnn, - adapter->wwpn, - (unsigned int) adapter->s_id, - adapter->hydra_version, - adapter->fsf_lic_version, - adapter->fc_link_speed); + "WWNN 0x%016Lx, " + "WWPN 0x%016Lx, " + "S_ID 0x%08x,\n" + "adapter version 0x%x, " + "LIC version 0x%x, " + "FC link speed %d Gb/s\n", + zfcp_get_busid_by_adapter(adapter), + (wwn_t) fc_host_node_name(shost), + (wwn_t) fc_host_port_name(shost), + fc_host_port_id(shost), + adapter->hydra_version, + adapter->fsf_lic_version, + fc_host_speed(shost)); if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { ZFCP_LOG_NORMAL("error: the adapter %s " "only supports newer control block " @@ -2055,7 +2059,6 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; } - zfcp_set_fc_host_attrs(adapter); return 0; } @@ -2259,6 +2262,7 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) { struct zfcp_adapter *adapter = fsf_req->adapter; + struct Scsi_Host *shost = adapter->scsi_host; struct fsf_qtcb *qtcb = fsf_req->qtcb; struct fsf_qtcb_bottom_port *bottom, *data; @@ -2277,9 +2281,10 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) adapter->physical_wwpn = bottom->wwpn; adapter->physical_s_id = bottom->fc_port_id; } else { - adapter->physical_wwpn = adapter->wwpn; - adapter->physical_s_id = adapter->s_id; + adapter->physical_wwpn = fc_host_port_name(shost); + adapter->physical_s_id = fc_host_port_id(shost); } + fc_host_maxframe_size(shost) = bottom->maximum_frame_size; break; case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index c1403a2..3dcd1bf 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -698,10 +698,16 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) { struct Scsi_Host *shost; + struct zfcp_port *port; shost = adapter->scsi_host; if (!shost) return; + read_lock_irq(&zfcp_data.config_lock); + list_for_each_entry(port, &adapter->port_list_head, list) + if (port->rport) + port->rport = NULL; + read_unlock_irq(&zfcp_data.config_lock); fc_remove_host(shost); scsi_remove_host(shost); scsi_host_put(shost); @@ -776,18 +782,6 @@ zfcp_get_node_name(struct scsi_target *starget) read_unlock_irqrestore(&zfcp_data.config_lock, flags); } -void -zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter) -{ - struct Scsi_Host *shost = adapter->scsi_host; - - fc_host_node_name(shost) = adapter->wwnn; - fc_host_port_name(shost) = adapter->wwpn; - strncpy(fc_host_serial_number(shost), adapter->serial_number, - min(FC_SERIAL_NUMBER_SIZE, 32)); - fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; -} - struct fc_function_template zfcp_transport_functions = { .get_starget_port_id = zfcp_get_port_id, .get_starget_port_name = zfcp_get_port_name, @@ -799,7 +793,10 @@ struct fc_function_template zfcp_transport_functions = { .show_host_node_name = 1, .show_host_port_name = 1, .show_host_supported_classes = 1, + .show_host_maxframe_size = 1, .show_host_serial_number = 1, + .show_host_speed = 1, + .show_host_port_id = 1, }; /** diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index c406ea5..0cd4352 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c @@ -62,9 +62,6 @@ static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct devi static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL); ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); -ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn); -ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn); -ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); @@ -72,13 +69,11 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); -ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", fc_topologies[adapter->fc_topology]); ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); -ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); @@ -257,9 +252,6 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_in_recovery.attr, &dev_attr_port_remove.attr, &dev_attr_port_add.attr, - &dev_attr_wwnn.attr, - &dev_attr_wwpn.attr, - &dev_attr_s_id.attr, &dev_attr_peer_wwnn.attr, &dev_attr_peer_wwpn.attr, &dev_attr_peer_d_id.attr, @@ -267,13 +259,11 @@ static struct attribute *zfcp_adapter_attrs[] = { &dev_attr_physical_s_id.attr, &dev_attr_card_version.attr, &dev_attr_lic_version.attr, - &dev_attr_fc_link_speed.attr, &dev_attr_fc_service_class.attr, &dev_attr_fc_topology.attr, &dev_attr_scsi_host_no.attr, &dev_attr_status.attr, &dev_attr_hardware_version.attr, - &dev_attr_serial_number.attr, NULL }; -- cgit v0.10.2 From eff4c654b1a4a5e5493fbdc3affa6dd48765c085 Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Mon, 19 Sep 2005 13:51:01 -0700 Subject: [PATCH] IB: Fix data length for RMPP SA sends We need to subtract off the header length from our payload length when sending multi-packet SA messages. Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 7c2f030..a64d6b4 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -334,10 +334,11 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, ret = -EINVAL; goto err_ah; } - /* Validate that management class can support RMPP */ + + /* Validate that the management class can support RMPP */ if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { hdr_len = offsetof(struct ib_sa_mad, data); - data_len = length; + data_len = length - hdr_len; } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) { hdr_len = offsetof(struct ib_vendor_mad, data); -- cgit v0.10.2 From 1d25cd6cc2528e4af12ab18e84fe95ed78f3f21a Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Mon, 19 Sep 2005 15:29:52 -0700 Subject: [IPV4]: fib_trie tnode stats refinements * Prints the route tnode and set the stats level deepth as before. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 1b63b48..3dd7078 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2029,7 +2029,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter, iter->tnode = (struct tnode *) n; iter->trie = t; iter->index = 0; - iter->depth = 0; + iter->depth = 1; return n; } return NULL; @@ -2274,11 +2274,12 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) seq_puts(seq, ":\n"); else seq_puts(seq, "
:\n"); - } else { - seq_indent(seq, iter->depth-1); - seq_printf(seq, " +-- %d.%d.%d.%d/%d\n", - NIPQUAD(prf), tn->pos); - } + } + seq_indent(seq, iter->depth-1); + seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n", + NIPQUAD(prf), tn->pos, tn->bits, tn->full_children, + tn->empty_children); + } else { struct leaf *l = (struct leaf *) n; int i; -- cgit v0.10.2 From 772cb712b1373d335ef2874ea357ec681edc754b Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Mon, 19 Sep 2005 15:31:18 -0700 Subject: [IPV4]: fib_trie RCU refinements * This patch is from Paul McKenney's RCU reviewing. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 3dd7078..90ae708 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -43,7 +43,7 @@ * 2 of the License, or (at your option) any later version. */ -#define VERSION "0.403" +#define VERSION "0.404" #include #include @@ -224,7 +224,7 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b) Consider a node 'n' and its parent 'tp'. If n is a leaf, every bit in its key is significant. Its presence is - necessitaded by path compression, since during a tree traversal (when + necessitated by path compression, since during a tree traversal (when searching for a leaf - unless we are doing an insertion) we will completely ignore all skipped bits we encounter. Thus we need to verify, at the end of a potentially successful search, that we have indeed been walking the @@ -836,11 +836,12 @@ static void trie_init(struct trie *t) #endif } -/* readside most use rcu_read_lock currently dump routines +/* readside must use rcu_read_lock currently dump routines via get_fa_head and dump */ -static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) +static struct leaf_info *find_leaf_info(struct leaf *l, int plen) { + struct hlist_head *head = &l->list; struct hlist_node *node; struct leaf_info *li; @@ -853,7 +854,7 @@ static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) static inline struct list_head * get_fa_head(struct leaf *l, int plen) { - struct leaf_info *li = find_leaf_info(&l->list, plen); + struct leaf_info *li = find_leaf_info(l, plen); if (!li) return NULL; @@ -1248,7 +1249,7 @@ err: } -/* should be clalled with rcu_read_lock */ +/* should be called with rcu_read_lock */ static inline int check_leaf(struct trie *t, struct leaf *l, t_key key, int *plen, const struct flowi *flp, struct fib_result *res) @@ -1590,7 +1591,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); l = fib_find_node(t, key); - li = find_leaf_info(&l->list, plen); + li = find_leaf_info(l, plen); list_del_rcu(&fa->fa_list); @@ -1714,7 +1715,6 @@ static int fn_trie_flush(struct fib_table *tb) t->revision++; - rcu_read_lock(); for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { found += trie_flush_leaf(t, l); @@ -1722,7 +1722,6 @@ static int fn_trie_flush(struct fib_table *tb) trie_leaf_remove(t, ll->key); ll = l; } - rcu_read_unlock(); if (ll && hlist_empty(&ll->list)) trie_leaf_remove(t, ll->key); @@ -2288,7 +2287,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) seq_indent(seq, iter->depth); seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val)); for (i = 32; i >= 0; i--) { - struct leaf_info *li = find_leaf_info(&l->list, i); + struct leaf_info *li = find_leaf_info(l, i); if (li) { struct fib_alias *fa; list_for_each_entry_rcu(fa, &li->falh, fa_list) { @@ -2384,7 +2383,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) return 0; for (i=32; i>=0; i--) { - struct leaf_info *li = find_leaf_info(&l->list, i); + struct leaf_info *li = find_leaf_info(l, i); struct fib_alias *fa; u32 mask, prefix; -- cgit v0.10.2 From 926b50f92a30090da2c1a8675de954c2d9b09732 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 19 Sep 2005 15:33:08 -0700 Subject: [NETFILTER]: Add new PPTP conntrack and NAT helper This new "version 3" PPTP conntrack/nat helper is finally ready for mainline inclusion. Special thanks to lots of last-minute bugfixing by Patric McHardy. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 7e033e9..2df446c 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -133,11 +133,13 @@ enum ip_conntrack_expect_events { #include #include +#include #include /* per conntrack: protocol private data */ union ip_conntrack_proto { /* insert conntrack proto private data here */ + struct ip_ct_gre gre; struct ip_ct_sctp sctp; struct ip_ct_tcp tcp; struct ip_ct_icmp icmp; @@ -148,6 +150,7 @@ union ip_conntrack_expect_proto { }; /* Add protocol helper include file here */ +#include #include #include #include @@ -155,12 +158,20 @@ union ip_conntrack_expect_proto { /* per conntrack: application helper private data */ union ip_conntrack_help { /* insert conntrack helper private data (master) here */ + struct ip_ct_pptp_master ct_pptp_info; struct ip_ct_ftp_master ct_ftp_info; struct ip_ct_irc_master ct_irc_info; }; #ifdef CONFIG_IP_NF_NAT_NEEDED #include +#include + +/* per conntrack: nat application helper private data */ +union ip_conntrack_nat_help { + /* insert nat helper private data here */ + struct ip_nat_pptp nat_pptp_info; +}; #endif #include @@ -223,6 +234,7 @@ struct ip_conntrack #ifdef CONFIG_IP_NF_NAT_NEEDED struct { struct ip_nat_info info; + union ip_conntrack_nat_help help; #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) int masq_index; diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h new file mode 100644 index 0000000..389e385 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h @@ -0,0 +1,332 @@ +/* PPTP constants and structs */ +#ifndef _CONNTRACK_PPTP_H +#define _CONNTRACK_PPTP_H + +/* state of the control session */ +enum pptp_ctrlsess_state { + PPTP_SESSION_NONE, /* no session present */ + PPTP_SESSION_ERROR, /* some session error */ + PPTP_SESSION_STOPREQ, /* stop_sess request seen */ + PPTP_SESSION_REQUESTED, /* start_sess request seen */ + PPTP_SESSION_CONFIRMED, /* session established */ +}; + +/* state of the call inside the control session */ +enum pptp_ctrlcall_state { + PPTP_CALL_NONE, + PPTP_CALL_ERROR, + PPTP_CALL_OUT_REQ, + PPTP_CALL_OUT_CONF, + PPTP_CALL_IN_REQ, + PPTP_CALL_IN_REP, + PPTP_CALL_IN_CONF, + PPTP_CALL_CLEAR_REQ, +}; + + +/* conntrack private data */ +struct ip_ct_pptp_master { + enum pptp_ctrlsess_state sstate; /* session state */ + + /* everything below is going to be per-expectation in newnat, + * since there could be more than one call within one session */ + enum pptp_ctrlcall_state cstate; /* call state */ + u_int16_t pac_call_id; /* call id of PAC, host byte order */ + u_int16_t pns_call_id; /* call id of PNS, host byte order */ + + /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack + * and therefore imposes a fixed limit on the number of maps */ + struct ip_ct_gre_keymap *keymap_orig, *keymap_reply; +}; + +/* conntrack_expect private member */ +struct ip_ct_pptp_expect { + enum pptp_ctrlcall_state cstate; /* call state */ + u_int16_t pac_call_id; /* call id of PAC */ + u_int16_t pns_call_id; /* call id of PNS */ +}; + + +#ifdef __KERNEL__ + +#define IP_CONNTR_PPTP PPTP_CONTROL_PORT + +#define PPTP_CONTROL_PORT 1723 + +#define PPTP_PACKET_CONTROL 1 +#define PPTP_PACKET_MGMT 2 + +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d + +struct pptp_pkt_hdr { + __u16 packetLength; + __u16 packetType; + __u32 magicCookie; +}; + +/* PptpControlMessageType values */ +#define PPTP_START_SESSION_REQUEST 1 +#define PPTP_START_SESSION_REPLY 2 +#define PPTP_STOP_SESSION_REQUEST 3 +#define PPTP_STOP_SESSION_REPLY 4 +#define PPTP_ECHO_REQUEST 5 +#define PPTP_ECHO_REPLY 6 +#define PPTP_OUT_CALL_REQUEST 7 +#define PPTP_OUT_CALL_REPLY 8 +#define PPTP_IN_CALL_REQUEST 9 +#define PPTP_IN_CALL_REPLY 10 +#define PPTP_IN_CALL_CONNECT 11 +#define PPTP_CALL_CLEAR_REQUEST 12 +#define PPTP_CALL_DISCONNECT_NOTIFY 13 +#define PPTP_WAN_ERROR_NOTIFY 14 +#define PPTP_SET_LINK_INFO 15 + +#define PPTP_MSG_MAX 15 + +/* PptpGeneralError values */ +#define PPTP_ERROR_CODE_NONE 0 +#define PPTP_NOT_CONNECTED 1 +#define PPTP_BAD_FORMAT 2 +#define PPTP_BAD_VALUE 3 +#define PPTP_NO_RESOURCE 4 +#define PPTP_BAD_CALLID 5 +#define PPTP_REMOVE_DEVICE_ERROR 6 + +struct PptpControlHeader { + __u16 messageType; + __u16 reserved; +}; + +/* FramingCapability Bitmap Values */ +#define PPTP_FRAME_CAP_ASYNC 0x1 +#define PPTP_FRAME_CAP_SYNC 0x2 + +/* BearerCapability Bitmap Values */ +#define PPTP_BEARER_CAP_ANALOG 0x1 +#define PPTP_BEARER_CAP_DIGITAL 0x2 + +struct PptpStartSessionRequest { + __u16 protocolVersion; + __u8 reserved1; + __u8 reserved2; + __u32 framingCapability; + __u32 bearerCapability; + __u16 maxChannels; + __u16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStartSessionResultCode Values */ +#define PPTP_START_OK 1 +#define PPTP_START_GENERAL_ERROR 2 +#define PPTP_START_ALREADY_CONNECTED 3 +#define PPTP_START_NOT_AUTHORIZED 4 +#define PPTP_START_UNKNOWN_PROTOCOL 5 + +struct PptpStartSessionReply { + __u16 protocolVersion; + __u8 resultCode; + __u8 generalErrorCode; + __u32 framingCapability; + __u32 bearerCapability; + __u16 maxChannels; + __u16 firmwareRevision; + __u8 hostName[64]; + __u8 vendorString[64]; +}; + +/* PptpStopReasons */ +#define PPTP_STOP_NONE 1 +#define PPTP_STOP_PROTOCOL 2 +#define PPTP_STOP_LOCAL_SHUTDOWN 3 + +struct PptpStopSessionRequest { + __u8 reason; +}; + +/* PptpStopSessionResultCode */ +#define PPTP_STOP_OK 1 +#define PPTP_STOP_GENERAL_ERROR 2 + +struct PptpStopSessionReply { + __u8 resultCode; + __u8 generalErrorCode; +}; + +struct PptpEchoRequest { + __u32 identNumber; +}; + +/* PptpEchoReplyResultCode */ +#define PPTP_ECHO_OK 1 +#define PPTP_ECHO_GENERAL_ERROR 2 + +struct PptpEchoReply { + __u32 identNumber; + __u8 resultCode; + __u8 generalErrorCode; + __u16 reserved; +}; + +/* PptpFramingType */ +#define PPTP_ASYNC_FRAMING 1 +#define PPTP_SYNC_FRAMING 2 +#define PPTP_DONT_CARE_FRAMING 3 + +/* PptpCallBearerType */ +#define PPTP_ANALOG_TYPE 1 +#define PPTP_DIGITAL_TYPE 2 +#define PPTP_DONT_CARE_BEARER_TYPE 3 + +struct PptpOutCallRequest { + __u16 callID; + __u16 callSerialNumber; + __u32 minBPS; + __u32 maxBPS; + __u32 bearerType; + __u32 framingType; + __u16 packetWindow; + __u16 packetProcDelay; + __u16 reserved1; + __u16 phoneNumberLength; + __u16 reserved2; + __u8 phoneNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpCallResultCode */ +#define PPTP_OUTCALL_CONNECT 1 +#define PPTP_OUTCALL_GENERAL_ERROR 2 +#define PPTP_OUTCALL_NO_CARRIER 3 +#define PPTP_OUTCALL_BUSY 4 +#define PPTP_OUTCALL_NO_DIAL_TONE 5 +#define PPTP_OUTCALL_TIMEOUT 6 +#define PPTP_OUTCALL_DONT_ACCEPT 7 + +struct PptpOutCallReply { + __u16 callID; + __u16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 causeCode; + __u32 connectSpeed; + __u16 packetWindow; + __u16 packetProcDelay; + __u32 physChannelID; +}; + +struct PptpInCallRequest { + __u16 callID; + __u16 callSerialNumber; + __u32 callBearerType; + __u32 physChannelID; + __u16 dialedNumberLength; + __u16 dialingNumberLength; + __u8 dialedNumber[64]; + __u8 dialingNumber[64]; + __u8 subAddress[64]; +}; + +/* PptpInCallResultCode */ +#define PPTP_INCALL_ACCEPT 1 +#define PPTP_INCALL_GENERAL_ERROR 2 +#define PPTP_INCALL_DONT_ACCEPT 3 + +struct PptpInCallReply { + __u16 callID; + __u16 peersCallID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 packetWindow; + __u16 packetProcDelay; + __u16 reserved; +}; + +struct PptpInCallConnected { + __u16 peersCallID; + __u16 reserved; + __u32 connectSpeed; + __u16 packetWindow; + __u16 packetProcDelay; + __u32 callFramingType; +}; + +struct PptpClearCallRequest { + __u16 callID; + __u16 reserved; +}; + +struct PptpCallDisconnectNotify { + __u16 callID; + __u8 resultCode; + __u8 generalErrorCode; + __u16 causeCode; + __u16 reserved; + __u8 callStatistics[128]; +}; + +struct PptpWanErrorNotify { + __u16 peersCallID; + __u16 reserved; + __u32 crcErrors; + __u32 framingErrors; + __u32 hardwareOverRuns; + __u32 bufferOverRuns; + __u32 timeoutErrors; + __u32 alignmentErrors; +}; + +struct PptpSetLinkInfo { + __u16 peersCallID; + __u16 reserved; + __u32 sendAccm; + __u32 recvAccm; +}; + + +struct pptp_priv_data { + __u16 call_id; + __u16 mcall_id; + __u16 pcall_id; +}; + +union pptp_ctrl_union { + struct PptpStartSessionRequest sreq; + struct PptpStartSessionReply srep; + struct PptpStopSessionRequest streq; + struct PptpStopSessionReply strep; + struct PptpOutCallRequest ocreq; + struct PptpOutCallReply ocack; + struct PptpInCallRequest icreq; + struct PptpInCallReply icack; + struct PptpInCallConnected iccon; + struct PptpClearCallRequest clrreq; + struct PptpCallDisconnectNotify disc; + struct PptpWanErrorNotify wanerr; + struct PptpSetLinkInfo setlink; +}; + +extern int +(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +extern int +(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +extern int +(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig, + struct ip_conntrack_expect *exp_reply); + +extern void +(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp); +#endif /* __KERNEL__ */ +#endif /* _CONNTRACK_PPTP_H */ diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h new file mode 100644 index 0000000..8d090ef --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h @@ -0,0 +1,114 @@ +#ifndef _CONNTRACK_PROTO_GRE_H +#define _CONNTRACK_PROTO_GRE_H +#include + +/* GRE PROTOCOL HEADER */ + +/* GRE Version field */ +#define GRE_VERSION_1701 0x0 +#define GRE_VERSION_PPTP 0x1 + +/* GRE Protocol field */ +#define GRE_PROTOCOL_PPTP 0x880B + +/* GRE Flags */ +#define GRE_FLAG_C 0x80 +#define GRE_FLAG_R 0x40 +#define GRE_FLAG_K 0x20 +#define GRE_FLAG_S 0x10 +#define GRE_FLAG_A 0x80 + +#define GRE_IS_C(f) ((f)&GRE_FLAG_C) +#define GRE_IS_R(f) ((f)&GRE_FLAG_R) +#define GRE_IS_K(f) ((f)&GRE_FLAG_K) +#define GRE_IS_S(f) ((f)&GRE_FLAG_S) +#define GRE_IS_A(f) ((f)&GRE_FLAG_A) + +/* GRE is a mess: Four different standards */ +struct gre_hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 rec:3, + srr:1, + seq:1, + key:1, + routing:1, + csum:1, + version:3, + reserved:4, + ack:1; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 csum:1, + routing:1, + key:1, + seq:1, + srr:1, + rec:3, + ack:1, + reserved:4, + version:3; +#else +#error "Adjust your defines" +#endif + __u16 protocol; +}; + +/* modified GRE header for PPTP */ +struct gre_hdr_pptp { + __u8 flags; /* bitfield */ + __u8 version; /* should be GRE_VERSION_PPTP */ + __u16 protocol; /* should be GRE_PROTOCOL_PPTP */ + __u16 payload_len; /* size of ppp payload, not inc. gre header */ + __u16 call_id; /* peer's call_id for this session */ + __u32 seq; /* sequence number. Present if S==1 */ + __u32 ack; /* seq number of highest packet recieved by */ + /* sender in this session */ +}; + + +/* this is part of ip_conntrack */ +struct ip_ct_gre { + unsigned int stream_timeout; + unsigned int timeout; +}; + +#ifdef __KERNEL__ +struct ip_conntrack_expect; +struct ip_conntrack; + +/* structure for original <-> reply keymap */ +struct ip_ct_gre_keymap { + struct list_head list; + + struct ip_conntrack_tuple tuple; +}; + +/* add new tuple->key_reply pair to keymap */ +int ip_ct_gre_keymap_add(struct ip_conntrack *ct, + struct ip_conntrack_tuple *t, + int reply); + +/* delete keymap entries */ +void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct); + + +/* get pointer to gre key, if present */ +static inline u_int32_t *gre_key(struct gre_hdr *greh) +{ + if (!greh->key) + return NULL; + if (greh->csum || greh->routing) + return (u_int32_t *) (greh+sizeof(*greh)+4); + return (u_int32_t *) (greh+sizeof(*greh)); +} + +/* get pointer ot gre csum, if present */ +static inline u_int16_t *gre_csum(struct gre_hdr *greh) +{ + if (!greh->csum) + return NULL; + return (u_int16_t *) (greh+sizeof(*greh)); +} + +#endif /* __KERNEL__ */ + +#endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h index c33f0b5..14dc0f7 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h @@ -28,6 +28,9 @@ union ip_conntrack_manip_proto struct { u_int16_t port; } sctp; + struct { + u_int16_t key; /* key is 32bit, pptp only uses 16 */ + } gre; }; /* The manipulable part of the tuple. */ @@ -61,6 +64,10 @@ struct ip_conntrack_tuple struct { u_int16_t port; } sctp; + struct { + u_int16_t key; /* key is 32bit, + * pptp only uses 16 */ + } gre; } u; /* The protocol. */ diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h new file mode 100644 index 0000000..eaf66c2 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_nat_pptp.h @@ -0,0 +1,11 @@ +/* PPTP constants and structs */ +#ifndef _NAT_PPTP_H +#define _NAT_PPTP_H + +/* conntrack private data */ +struct ip_nat_pptp { + u_int16_t pns_call_id; /* NAT'ed PNS call id */ + u_int16_t pac_call_id; /* NAT'ed PAC call id */ +}; + +#endif /* _NAT_PPTP_H */ diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index e2162d2..3cf9b45 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -137,6 +137,22 @@ config IP_NF_AMANDA To compile it as a module, choose M here. If unsure, say Y. +config IP_NF_PPTP + tristate 'PPTP protocol support' + help + This module adds support for PPTP (Point to Point Tunnelling + Protocol, RFC2637) conncection tracking and NAT. + + If you are running PPTP sessions over a stateful firewall or NAT + box, you may want to enable this feature. + + Please note that not all PPTP modes of operation are supported yet. + For more info, read top of the file + net/ipv4/netfilter/ip_conntrack_pptp.c + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + config IP_NF_QUEUE tristate "IP Userspace queueing via NETLINK (OBSOLETE)" help @@ -621,6 +637,12 @@ config IP_NF_NAT_AMANDA default IP_NF_NAT if IP_NF_AMANDA=y default m if IP_NF_AMANDA=m +config IP_NF_NAT_PPTP + tristate + depends on IP_NF_NAT!=n && IP_NF_PPTP!=n + default IP_NF_NAT if IP_NF_PPTP=y + default m if IP_NF_PPTP=m + # mangle + specific targets config IP_NF_MANGLE tristate "Packet mangling" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 1ba0db7..3d45d3c 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -6,6 +6,9 @@ ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o +ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o +ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o + # connection tracking obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o @@ -17,6 +20,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o # connection tracking helpers +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o @@ -24,6 +28,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o # NAT helpers +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c new file mode 100644 index 0000000..79db5b7 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -0,0 +1,805 @@ +/* + * ip_conntrack_pptp.c - Version 3.0 + * + * Connection tracking support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * Limitations: + * - We blindly assume that control connections are always + * established in PNS->PAC direction. This is a violation + * of RFFC2673 + * - We can only support one single call within each session + * + * TODO: + * - testing of incoming PPTP calls + * + * Changes: + * 2002-02-05 - Version 1.3 + * - Call ip_conntrack_unexpect_related() from + * pptp_destroy_siblings() to destroy expectations in case + * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen + * (Philip Craig ) + * - Add Version information at module loadtime + * 2002-02-10 - Version 1.6 + * - move to C99 style initializers + * - remove second expectation if first arrives + * 2004-10-22 - Version 2.0 + * - merge Mandrake's 2.6.x port with recent 2.6.x API changes + * - fix lots of linear skb assumptions from Mandrake's port + * 2005-06-10 - Version 2.1 + * - use ip_conntrack_expect_free() instead of kfree() on the + * expect's (which are from the slab for quite some time) + * 2005-06-10 - Version 3.0 + * - port helper to post-2.6.11 API changes, + * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/) + * 2005-07-30 - Version 3.1 + * - port helper to 2.6.13 API changes + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define IP_CT_PPTP_VERSION "3.1" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); + +static DEFINE_SPINLOCK(ip_pptp_lock); + +int +(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +int +(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq); + +int +(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig, + struct ip_conntrack_expect *expect_reply); + +void +(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp); + +#if 0 +/* PptpControlMessageType names */ +const char *pptp_msg_name[] = { + "UNKNOWN_MESSAGE", + "START_SESSION_REQUEST", + "START_SESSION_REPLY", + "STOP_SESSION_REQUEST", + "STOP_SESSION_REPLY", + "ECHO_REQUEST", + "ECHO_REPLY", + "OUT_CALL_REQUEST", + "OUT_CALL_REPLY", + "IN_CALL_REQUEST", + "IN_CALL_REPLY", + "IN_CALL_CONNECT", + "CALL_CLEAR_REQUEST", + "CALL_DISCONNECT_NOTIFY", + "WAN_ERROR_NOTIFY", + "SET_LINK_INFO" +}; +EXPORT_SYMBOL(pptp_msg_name); +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) +#else +#define DEBUGP(format, args...) +#endif + +#define SECS *HZ +#define MINS * 60 SECS +#define HOURS * 60 MINS + +#define PPTP_GRE_TIMEOUT (10 MINS) +#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS) + +static void pptp_expectfn(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp) +{ + DEBUGP("increasing timeouts\n"); + + /* increase timeout of GRE data channel conntrack entry */ + ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; + ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; + + /* Can you see how rusty this code is, compared with the pre-2.6.11 + * one? That's what happened to my shiny newnat of 2002 ;( -HW */ + + if (!ip_nat_pptp_hook_expectfn) { + struct ip_conntrack_tuple inv_t; + struct ip_conntrack_expect *exp_other; + + /* obviously this tuple inversion only works until you do NAT */ + invert_tuplepr(&inv_t, &exp->tuple); + DEBUGP("trying to unexpect other dir: "); + DUMP_TUPLE(&inv_t); + + exp_other = ip_conntrack_expect_find(&inv_t); + if (exp_other) { + /* delete other expectation. */ + DEBUGP("found\n"); + ip_conntrack_unexpect_related(exp_other); + ip_conntrack_expect_put(exp_other); + } else { + DEBUGP("not found\n"); + } + } else { + /* we need more than simple inversion */ + ip_nat_pptp_hook_expectfn(ct, exp); + } +} + +static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) +{ + struct ip_conntrack_tuple_hash *h; + struct ip_conntrack_expect *exp; + + DEBUGP("trying to timeout ct or exp for tuple "); + DUMP_TUPLE(t); + + h = ip_conntrack_find_get(t, NULL); + if (h) { + struct ip_conntrack *sibling = tuplehash_to_ctrack(h); + DEBUGP("setting timeout of conntrack %p to 0\n", sibling); + sibling->proto.gre.timeout = 0; + sibling->proto.gre.stream_timeout = 0; + /* refresh_acct will not modify counters if skb == NULL */ + if (del_timer(&sibling->timeout)) + sibling->timeout.function((unsigned long)sibling); + ip_conntrack_put(sibling); + return 1; + } else { + exp = ip_conntrack_expect_find(t); + if (exp) { + DEBUGP("unexpect_related of expect %p\n", exp); + ip_conntrack_unexpect_related(exp); + ip_conntrack_expect_put(exp); + return 1; + } + } + + return 0; +} + + +/* timeout GRE data connections */ +static void pptp_destroy_siblings(struct ip_conntrack *ct) +{ + struct ip_conntrack_tuple t; + + /* Since ct->sibling_list has literally rusted away in 2.6.11, + * we now need another way to find out about our sibling + * contrack and expects... -HW */ + + /* try original (pns->pac) tuple */ + memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t)); + t.dst.protonum = IPPROTO_GRE; + t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); + t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); + + if (!destroy_sibling_or_exp(&t)) + DEBUGP("failed to timeout original pns->pac ct/exp\n"); + + /* try reply (pac->pns) tuple */ + memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); + t.dst.protonum = IPPROTO_GRE; + t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); + t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); + + if (!destroy_sibling_or_exp(&t)) + DEBUGP("failed to timeout reply pac->pns ct/exp\n"); +} + +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */ +static inline int +exp_gre(struct ip_conntrack *master, + u_int32_t seq, + u_int16_t callid, + u_int16_t peer_callid) +{ + struct ip_conntrack_tuple inv_tuple; + struct ip_conntrack_tuple exp_tuples[] = { + /* tuple in original direction, PNS->PAC */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip, + .u = { .gre = { .key = peer_callid } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip, + .u = { .gre = { .key = callid } }, + .protonum = IPPROTO_GRE + }, + }, + /* tuple in reply direction, PAC->PNS */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, + .u = { .gre = { .key = callid } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, + .u = { .gre = { .key = peer_callid } }, + .protonum = IPPROTO_GRE + }, + } + }; + struct ip_conntrack_expect *exp_orig, *exp_reply; + int ret = 1; + + exp_orig = ip_conntrack_expect_alloc(master); + if (exp_orig == NULL) + goto out; + + exp_reply = ip_conntrack_expect_alloc(master); + if (exp_reply == NULL) + goto out_put_orig; + + memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple)); + + exp_orig->mask.src.ip = 0xffffffff; + exp_orig->mask.src.u.all = 0; + exp_orig->mask.dst.u.all = 0; + exp_orig->mask.dst.u.gre.key = 0xffff; + exp_orig->mask.dst.ip = 0xffffffff; + exp_orig->mask.dst.protonum = 0xff; + + exp_orig->master = master; + exp_orig->expectfn = pptp_expectfn; + exp_orig->flags = 0; + + exp_orig->dir = IP_CT_DIR_ORIGINAL; + + /* both expectations are identical apart from tuple */ + memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); + memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); + + exp_reply->dir = !exp_orig->dir; + + if (ip_nat_pptp_hook_exp_gre) + ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); + else { + + DEBUGP("calling expect_related PNS->PAC"); + DUMP_TUPLE(&exp_orig->tuple); + + if (ip_conntrack_expect_related(exp_orig) != 0) { + DEBUGP("cannot expect_related()\n"); + goto out_put_both; + } + + DEBUGP("calling expect_related PAC->PNS"); + DUMP_TUPLE(&exp_reply->tuple); + + if (ip_conntrack_expect_related(exp_reply) != 0) { + DEBUGP("cannot expect_related()\n"); + goto out_unexpect_orig; + } + + /* Add GRE keymap entries */ + if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) { + DEBUGP("cannot keymap_add() exp\n"); + goto out_unexpect_both; + } + + invert_tuplepr(&inv_tuple, &exp_reply->tuple); + if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) { + ip_ct_gre_keymap_destroy(master); + DEBUGP("cannot keymap_add() exp_inv\n"); + goto out_unexpect_both; + } + ret = 0; + } + +out_put_both: + ip_conntrack_expect_put(exp_reply); +out_put_orig: + ip_conntrack_expect_put(exp_orig); +out: + return ret; + +out_unexpect_both: + ip_conntrack_unexpect_related(exp_reply); +out_unexpect_orig: + ip_conntrack_unexpect_related(exp_orig); + goto out_put_both; +} + +static inline int +pptp_inbound_pkt(struct sk_buff **pskb, + struct tcphdr *tcph, + unsigned int nexthdr_off, + unsigned int datalen, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + u_int16_t msg, *cid, *pcid; + u_int32_t seq; + + ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); + if (!ctlh) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } + nexthdr_off += sizeof(_ctlh); + datalen -= sizeof(_ctlh); + + reqlen = datalen; + if (reqlen > sizeof(*pptpReq)) + reqlen = sizeof(*pptpReq); + pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); + if (!pptpReq) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } + + msg = ntohs(ctlh->messageType); + DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); + + switch (msg) { + case PPTP_START_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.srep)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server confirms new control session */ + if (info->sstate < PPTP_SESSION_REQUESTED) { + DEBUGP("%s without START_SESS_REQUEST\n", + pptp_msg_name[msg]); + break; + } + if (pptpReq->srep.resultCode == PPTP_START_OK) + info->sstate = PPTP_SESSION_CONFIRMED; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_STOP_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.strep)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server confirms end of control session */ + if (info->sstate > PPTP_SESSION_STOPREQ) { + DEBUGP("%s without STOP_SESS_REQUEST\n", + pptp_msg_name[msg]); + break; + } + if (pptpReq->strep.resultCode == PPTP_STOP_OK) + info->sstate = PPTP_SESSION_NONE; + else + info->sstate = PPTP_SESSION_ERROR; + break; + + case PPTP_OUT_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.ocack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server accepted call, we now expect GRE frames */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } + if (info->cstate != PPTP_CALL_OUT_REQ && + info->cstate != PPTP_CALL_OUT_CONF) { + DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]); + break; + } + if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { + info->cstate = PPTP_CALL_NONE; + break; + } + + cid = &pptpReq->ocack.callID; + pcid = &pptpReq->ocack.peersCallID; + + info->pac_call_id = ntohs(*cid); + + if (htons(info->pns_call_id) != *pcid) { + DEBUGP("%s for unknown callid %u\n", + pptp_msg_name[msg], ntohs(*pcid)); + break; + } + + DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], + ntohs(*cid), ntohs(*pcid)); + + info->cstate = PPTP_CALL_OUT_CONF; + + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); + break; + + case PPTP_IN_CALL_REQUEST: + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server tells us about incoming call request */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } + pcid = &pptpReq->icack.peersCallID; + DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); + info->cstate = PPTP_CALL_IN_REQ; + info->pac_call_id = ntohs(*pcid); + break; + + case PPTP_IN_CALL_CONNECT: + if (reqlen < sizeof(_pptpReq.iccon)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server tells us about incoming call established */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } + if (info->sstate != PPTP_CALL_IN_REP + && info->sstate != PPTP_CALL_IN_CONF) { + DEBUGP("%s but never sent IN_CALL_REPLY\n", + pptp_msg_name[msg]); + break; + } + + pcid = &pptpReq->iccon.peersCallID; + cid = &info->pac_call_id; + + if (info->pns_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown CallID %u\n", + pptp_msg_name[msg], ntohs(*cid)); + break; + } + + DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); + info->cstate = PPTP_CALL_IN_CONF; + + /* we expect a GRE connection from PAC to PNS */ + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); + + break; + + case PPTP_CALL_DISCONNECT_NOTIFY: + if (reqlen < sizeof(_pptpReq.disc)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* server confirms disconnect */ + cid = &pptpReq->disc.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_destroy_siblings(ct); + break; + + case PPTP_WAN_ERROR_NOTIFY: + break; + + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + default: + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) + ? pptp_msg_name[msg]:pptp_msg_name[0], msg); + break; + } + + + if (ip_nat_pptp_hook_inbound) + return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, + pptpReq); + + return NF_ACCEPT; + +} + +static inline int +pptp_outbound_pkt(struct sk_buff **pskb, + struct tcphdr *tcph, + unsigned int nexthdr_off, + unsigned int datalen, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + u_int16_t msg, *cid, *pcid; + + ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); + if (!ctlh) + return NF_ACCEPT; + nexthdr_off += sizeof(_ctlh); + datalen -= sizeof(_ctlh); + + reqlen = datalen; + if (reqlen > sizeof(*pptpReq)) + reqlen = sizeof(*pptpReq); + pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); + if (!pptpReq) + return NF_ACCEPT; + + msg = ntohs(ctlh->messageType); + DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); + + switch (msg) { + case PPTP_START_SESSION_REQUEST: + /* client requests for new control session */ + if (info->sstate != PPTP_SESSION_NONE) { + DEBUGP("%s but we already have one", + pptp_msg_name[msg]); + } + info->sstate = PPTP_SESSION_REQUESTED; + break; + case PPTP_STOP_SESSION_REQUEST: + /* client requests end of control session */ + info->sstate = PPTP_SESSION_STOPREQ; + break; + + case PPTP_OUT_CALL_REQUEST: + if (reqlen < sizeof(_pptpReq.ocreq)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + /* FIXME: break; */ + } + + /* client initiating connection to server */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", + pptp_msg_name[msg]); + break; + } + info->cstate = PPTP_CALL_OUT_REQ; + /* track PNS call id */ + cid = &pptpReq->ocreq.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); + info->pns_call_id = ntohs(*cid); + break; + case PPTP_IN_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + + /* client answers incoming call */ + if (info->cstate != PPTP_CALL_IN_REQ + && info->cstate != PPTP_CALL_IN_REP) { + DEBUGP("%s without incall_req\n", + pptp_msg_name[msg]); + break; + } + if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { + info->cstate = PPTP_CALL_NONE; + break; + } + pcid = &pptpReq->icack.peersCallID; + if (info->pac_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown call %u\n", + pptp_msg_name[msg], ntohs(*pcid)); + break; + } + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); + /* part two of the three-way handshake */ + info->cstate = PPTP_CALL_IN_REP; + info->pns_call_id = ntohs(pptpReq->icack.callID); + break; + + case PPTP_CALL_CLEAR_REQUEST: + /* client requests hangup of call */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("CLEAR_CALL but no session\n"); + break; + } + /* FUTURE: iterate over all calls and check if + * call ID is valid. We don't do this without newnat, + * because we only know about last call */ + info->cstate = PPTP_CALL_CLEAR_REQ; + break; + case PPTP_SET_LINK_INFO: + break; + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* I don't have to explain these ;) */ + break; + default: + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? + pptp_msg_name[msg]:pptp_msg_name[0], msg); + /* unknown: no need to create GRE masq table entry */ + break; + } + + if (ip_nat_pptp_hook_outbound) + return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, + pptpReq); + + return NF_ACCEPT; +} + + +/* track caller id inside control connection, call expect_related */ +static int +conntrack_pptp_help(struct sk_buff **pskb, + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) + +{ + struct pptp_pkt_hdr _pptph, *pptph; + struct tcphdr _tcph, *tcph; + u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; + u_int32_t datalen; + int dir = CTINFO2DIR(ctinfo); + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; + unsigned int nexthdr_off; + + int oldsstate, oldcstate; + int ret; + + /* don't do any tracking before tcp handshake complete */ + if (ctinfo != IP_CT_ESTABLISHED + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { + DEBUGP("ctinfo = %u, skipping\n", ctinfo); + return NF_ACCEPT; + } + + nexthdr_off = (*pskb)->nh.iph->ihl*4; + tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); + BUG_ON(!tcph); + nexthdr_off += tcph->doff * 4; + datalen = tcplen - tcph->doff * 4; + + if (tcph->fin || tcph->rst) { + DEBUGP("RST/FIN received, timeouting GRE\n"); + /* can't do this after real newnat */ + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_destroy_siblings(ct); + } + + pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); + if (!pptph) { + DEBUGP("no full PPTP header, can't track\n"); + return NF_ACCEPT; + } + nexthdr_off += sizeof(_pptph); + datalen -= sizeof(_pptph); + + /* if it's not a control message we can't do anything with it */ + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { + DEBUGP("not a control packet\n"); + return NF_ACCEPT; + } + + oldsstate = info->sstate; + oldcstate = info->cstate; + + spin_lock_bh(&ip_pptp_lock); + + /* FIXME: We just blindly assume that the control connection is always + * established from PNS->PAC. However, RFC makes no guarantee */ + if (dir == IP_CT_DIR_ORIGINAL) + /* client -> server (PNS -> PAC) */ + ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, + ctinfo); + else + /* server -> client (PAC -> PNS) */ + ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, + ctinfo); + DEBUGP("sstate: %d->%d, cstate: %d->%d\n", + oldsstate, info->sstate, oldcstate, info->cstate); + spin_unlock_bh(&ip_pptp_lock); + + return ret; +} + +/* control protocol helper */ +static struct ip_conntrack_helper pptp = { + .list = { NULL, NULL }, + .name = "pptp", + .me = THIS_MODULE, + .max_expected = 2, + .timeout = 5 * 60, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(PPTP_CONTROL_PORT) } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xff + } + }, + .help = conntrack_pptp_help +}; + +extern void __exit ip_ct_proto_gre_fini(void); +extern int __init ip_ct_proto_gre_init(void); + +/* ip_conntrack_pptp initialization */ +static int __init init(void) +{ + int retcode; + + retcode = ip_ct_proto_gre_init(); + if (retcode < 0) + return retcode; + + DEBUGP(" registering helper\n"); + if ((retcode = ip_conntrack_helper_register(&pptp))) { + printk(KERN_ERR "Unable to register conntrack application " + "helper for pptp: %d\n", retcode); + ip_ct_proto_gre_fini(); + return retcode; + } + + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION); + return 0; +} + +static void __exit fini(void) +{ + ip_conntrack_helper_unregister(&pptp); + ip_ct_proto_gre_fini(); + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION); +} + +module_init(init); +module_exit(fini); + +EXPORT_SYMBOL(ip_nat_pptp_hook_outbound); +EXPORT_SYMBOL(ip_nat_pptp_hook_inbound); +EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre); +EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn); diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c new file mode 100644 index 0000000..de3cb9d --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -0,0 +1,327 @@ +/* + * ip_conntrack_proto_gre.c - Version 3.0 + * + * Connection tracking protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_RWLOCK(ip_ct_gre_lock); +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + +#include +#include +#include +#include + +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE"); + +/* shamelessly stolen from ip_conntrack_proto_udp.c */ +#define GRE_TIMEOUT (30*HZ) +#define GRE_STREAM_TIMEOUT (180*HZ) + +#if 0 +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \ + NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \ + NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key)) +#else +#define DEBUGP(x, args...) +#define DUMP_TUPLE_GRE(x) +#endif + +/* GRE KEYMAP HANDLING FUNCTIONS */ +static LIST_HEAD(gre_keymap_list); + +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km, + const struct ip_conntrack_tuple *t) +{ + return ((km->tuple.src.ip == t->src.ip) && + (km->tuple.dst.ip == t->dst.ip) && + (km->tuple.dst.protonum == t->dst.protonum) && + (km->tuple.dst.u.all == t->dst.u.all)); +} + +/* look up the source key for a given tuple */ +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t) +{ + struct ip_ct_gre_keymap *km; + u_int32_t key = 0; + + read_lock_bh(&ip_ct_gre_lock); + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, + struct ip_ct_gre_keymap *, t); + if (km) + key = km->tuple.src.u.gre.key; + read_unlock_bh(&ip_ct_gre_lock); + + DEBUGP("lookup src key 0x%x up key for ", key); + DUMP_TUPLE_GRE(t); + + return key; +} + +/* add a single keymap entry, associate with specified master ct */ +int +ip_ct_gre_keymap_add(struct ip_conntrack *ct, + struct ip_conntrack_tuple *t, int reply) +{ + struct ip_ct_gre_keymap **exist_km, *km, *old; + + if (!ct->helper || strcmp(ct->helper->name, "pptp")) { + DEBUGP("refusing to add GRE keymap to non-pptp session\n"); + return -1; + } + + if (!reply) + exist_km = &ct->help.ct_pptp_info.keymap_orig; + else + exist_km = &ct->help.ct_pptp_info.keymap_reply; + + if (*exist_km) { + /* check whether it's a retransmission */ + old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, + struct ip_ct_gre_keymap *, t); + if (old == *exist_km) { + DEBUGP("retransmission\n"); + return 0; + } + + DEBUGP("trying to override keymap_%s for ct %p\n", + reply? "reply":"orig", ct); + return -EEXIST; + } + + km = kmalloc(sizeof(*km), GFP_ATOMIC); + if (!km) + return -ENOMEM; + + memcpy(&km->tuple, t, sizeof(*t)); + *exist_km = km; + + DEBUGP("adding new entry %p: ", km); + DUMP_TUPLE_GRE(&km->tuple); + + write_lock_bh(&ip_ct_gre_lock); + list_append(&gre_keymap_list, km); + write_unlock_bh(&ip_ct_gre_lock); + + return 0; +} + +/* destroy the keymap entries associated with specified master ct */ +void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct) +{ + DEBUGP("entering for ct %p\n", ct); + + if (!ct->helper || strcmp(ct->helper->name, "pptp")) { + DEBUGP("refusing to destroy GRE keymap to non-pptp session\n"); + return; + } + + write_lock_bh(&ip_ct_gre_lock); + if (ct->help.ct_pptp_info.keymap_orig) { + DEBUGP("removing %p from list\n", + ct->help.ct_pptp_info.keymap_orig); + list_del(&ct->help.ct_pptp_info.keymap_orig->list); + kfree(ct->help.ct_pptp_info.keymap_orig); + ct->help.ct_pptp_info.keymap_orig = NULL; + } + if (ct->help.ct_pptp_info.keymap_reply) { + DEBUGP("removing %p from list\n", + ct->help.ct_pptp_info.keymap_reply); + list_del(&ct->help.ct_pptp_info.keymap_reply->list); + kfree(ct->help.ct_pptp_info.keymap_reply); + ct->help.ct_pptp_info.keymap_reply = NULL; + } + write_unlock_bh(&ip_ct_gre_lock); +} + + +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ + +/* invert gre part of tuple */ +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *orig) +{ + tuple->dst.u.gre.key = orig->src.u.gre.key; + tuple->src.u.gre.key = orig->dst.u.gre.key; + + return 1; +} + +/* gre hdr info to tuple */ +static int gre_pkt_to_tuple(const struct sk_buff *skb, + unsigned int dataoff, + struct ip_conntrack_tuple *tuple) +{ + struct gre_hdr_pptp _pgrehdr, *pgrehdr; + u_int32_t srckey; + struct gre_hdr _grehdr, *grehdr; + + /* first only delinearize old RFC1701 GRE header */ + grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); + if (!grehdr || grehdr->version != GRE_VERSION_PPTP) { + /* try to behave like "ip_conntrack_proto_generic" */ + tuple->src.u.all = 0; + tuple->dst.u.all = 0; + return 1; + } + + /* PPTP header is variable length, only need up to the call_id field */ + pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr); + if (!pgrehdr) + return 1; + + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { + DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); + return 0; + } + + tuple->dst.u.gre.key = pgrehdr->call_id; + srckey = gre_keymap_lookup(tuple); + tuple->src.u.gre.key = srckey; + + return 1; +} + +/* print gre part of tuple */ +static int gre_print_tuple(struct seq_file *s, + const struct ip_conntrack_tuple *tuple) +{ + return seq_printf(s, "srckey=0x%x dstkey=0x%x ", + ntohs(tuple->src.u.gre.key), + ntohs(tuple->dst.u.gre.key)); +} + +/* print private data for conntrack */ +static int gre_print_conntrack(struct seq_file *s, + const struct ip_conntrack *ct) +{ + return seq_printf(s, "timeout=%u, stream_timeout=%u ", + (ct->proto.gre.timeout / HZ), + (ct->proto.gre.stream_timeout / HZ)); +} + +/* Returns verdict for packet, and may modify conntrack */ +static int gre_packet(struct ip_conntrack *ct, + const struct sk_buff *skb, + enum ip_conntrack_info conntrackinfo) +{ + /* If we've seen traffic both ways, this is a GRE connection. + * Extend timeout. */ + if (ct->status & IPS_SEEN_REPLY) { + ip_ct_refresh_acct(ct, conntrackinfo, skb, + ct->proto.gre.stream_timeout); + /* Also, more likely to be important, and not a probe. */ + set_bit(IPS_ASSURED_BIT, &ct->status); + } else + ip_ct_refresh_acct(ct, conntrackinfo, skb, + ct->proto.gre.timeout); + + return NF_ACCEPT; +} + +/* Called when a new connection for this protocol found. */ +static int gre_new(struct ip_conntrack *ct, + const struct sk_buff *skb) +{ + DEBUGP(": "); + DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + + /* initialize to sane value. Ideally a conntrack helper + * (e.g. in case of pptp) is increasing them */ + ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT; + ct->proto.gre.timeout = GRE_TIMEOUT; + + return 1; +} + +/* Called when a conntrack entry has already been removed from the hashes + * and is about to be deleted from memory */ +static void gre_destroy(struct ip_conntrack *ct) +{ + struct ip_conntrack *master = ct->master; + DEBUGP(" entering\n"); + + if (!master) + DEBUGP("no master !?!\n"); + else + ip_ct_gre_keymap_destroy(master); +} + +/* protocol helper struct */ +static struct ip_conntrack_protocol gre = { + .proto = IPPROTO_GRE, + .name = "gre", + .pkt_to_tuple = gre_pkt_to_tuple, + .invert_tuple = gre_invert_tuple, + .print_tuple = gre_print_tuple, + .print_conntrack = gre_print_conntrack, + .packet = gre_packet, + .new = gre_new, + .destroy = gre_destroy, + .me = THIS_MODULE, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr, + .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple, +#endif +}; + +/* ip_conntrack_proto_gre initialization */ +int __init ip_ct_proto_gre_init(void) +{ + return ip_conntrack_protocol_register(&gre); +} + +void __exit ip_ct_proto_gre_fini(void) +{ + struct list_head *pos, *n; + + /* delete all keymap entries */ + write_lock_bh(&ip_ct_gre_lock); + list_for_each_safe(pos, n, &gre_keymap_list) { + DEBUGP("deleting keymap %p at module unload time\n", pos); + list_del(pos); + kfree(pos); + } + write_unlock_bh(&ip_ct_gre_lock); + + ip_conntrack_protocol_unregister(&gre); +} + +EXPORT_SYMBOL(ip_ct_gre_keymap_add); +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy); diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c new file mode 100644 index 0000000..3cdd068 --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -0,0 +1,401 @@ +/* + * ip_nat_pptp.c - Version 3.0 + * + * NAT support for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + * TODO: - NAT to a unique tuple, not to TCP source port + * (needs netfilter tuple reservation) + * + * Changes: + * 2002-02-10 - Version 1.3 + * - Use ip_nat_mangle_tcp_packet() because of cloned skb's + * in local connections (Philip Craig ) + * - add checks for magicCookie and pptp version + * - make argument list of pptp_{out,in}bound_packet() shorter + * - move to C99 style initializers + * - print version number at module loadtime + * 2003-09-22 - Version 1.5 + * - use SNATed tcp sourceport as callid, since we get called before + * TCP header is mangled (Philip Craig ) + * 2004-10-22 - Version 2.0 + * - kernel 2.6.x version + * 2005-06-10 - Version 3.0 + * - kernel >= 2.6.11 version, + * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/) + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IP_NAT_PPTP_VERSION "3.0" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); + + +#if 0 +extern const char *pptp_msg_name[]; +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ + __FUNCTION__, ## args) +#else +#define DEBUGP(format, args...) +#endif + +static void pptp_nat_expected(struct ip_conntrack *ct, + struct ip_conntrack_expect *exp) +{ + struct ip_conntrack *master = ct->master; + struct ip_conntrack_expect *other_exp; + struct ip_conntrack_tuple t; + struct ip_ct_pptp_master *ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info; + + ct_pptp_info = &master->help.ct_pptp_info; + nat_pptp_info = &master->nat.help.nat_pptp_info; + + /* And here goes the grand finale of corrosion... */ + + if (exp->dir == IP_CT_DIR_ORIGINAL) { + DEBUGP("we are PNS->PAC\n"); + /* therefore, build tuple for PAC->PNS */ + t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id); + t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id); + t.dst.protonum = IPPROTO_GRE; + } else { + DEBUGP("we are PAC->PNS\n"); + /* build tuple for PNS->PAC */ + t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + t.src.u.gre.key = + htons(master->nat.help.nat_pptp_info.pns_call_id); + t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + t.dst.u.gre.key = + htons(master->nat.help.nat_pptp_info.pac_call_id); + t.dst.protonum = IPPROTO_GRE; + } + + DEBUGP("trying to unexpect other dir: "); + DUMP_TUPLE(&t); + other_exp = ip_conntrack_expect_find(&t); + if (other_exp) { + ip_conntrack_unexpect_related(other_exp); + ip_conntrack_expect_put(other_exp); + DEBUGP("success\n"); + } else { + DEBUGP("not found!\n"); + } + + ip_nat_follow_master(ct, exp); +} + +/* outbound packets == from PNS to PAC */ +static int +pptp_outbound_pkt(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) + +{ + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; + + u_int16_t msg, *cid = NULL, new_callid; + + new_callid = htons(ct_pptp_info->pns_call_id); + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REQUEST: + cid = &pptpReq->ocreq.callID; + /* FIXME: ideally we would want to reserve a call ID + * here. current netfilter NAT core is not able to do + * this :( For now we use TCP source port. This breaks + * multiple calls within one control session */ + + /* save original call ID in nat_info */ + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; + + /* don't use tcph->source since we are at a DSTmanip + * hook (e.g. PREROUTING) and pkt is not mangled yet */ + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; + + /* save new call ID in ct info */ + ct_pptp_info->pns_call_id = ntohs(new_callid); + break; + case PPTP_IN_CALL_REPLY: + cid = &pptpReq->icreq.callID; + break; + case PPTP_CALL_CLEAR_REQUEST: + cid = &pptpReq->clrreq.callID; + break; + default: + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, + (msg <= PPTP_MSG_MAX)? + pptp_msg_name[msg]:pptp_msg_name[0]); + /* fall through */ + + case PPTP_SET_LINK_INFO: + /* only need to NAT in case PAC is behind NAT box */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass + * down to here */ + + IP_NF_ASSERT(cid); + + DEBUGP("altering call id from 0x%04x to 0x%04x\n", + ntohs(*cid), ntohs(new_callid)); + + /* mangle packet */ + if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), + sizeof(new_callid), + (char *)&new_callid, + sizeof(new_callid)) == 0) + return NF_DROP; + + return NF_ACCEPT; +} + +static int +pptp_exp_gre(struct ip_conntrack_expect *expect_orig, + struct ip_conntrack_expect *expect_reply) +{ + struct ip_ct_pptp_master *ct_pptp_info = + &expect_orig->master->help.ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info = + &expect_orig->master->nat.help.nat_pptp_info; + + struct ip_conntrack *ct = expect_orig->master; + + struct ip_conntrack_tuple inv_t; + struct ip_conntrack_tuple *orig_t, *reply_t; + + /* save original PAC call ID in nat_info */ + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; + + /* alter expectation */ + orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; + + /* alter expectation for PNS->PAC direction */ + invert_tuplepr(&inv_t, &expect_orig->tuple); + expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); + expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); + expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); + inv_t.src.ip = reply_t->src.ip; + inv_t.dst.ip = reply_t->dst.ip; + inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); + inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); + + if (!ip_conntrack_expect_related(expect_orig)) { + DEBUGP("successfully registered expect\n"); + } else { + DEBUGP("can't expect_related(expect_orig)\n"); + return 1; + } + + /* alter expectation for PAC->PNS direction */ + invert_tuplepr(&inv_t, &expect_reply->tuple); + expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); + expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); + expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); + inv_t.src.ip = orig_t->src.ip; + inv_t.dst.ip = orig_t->dst.ip; + inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); + inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); + + if (!ip_conntrack_expect_related(expect_reply)) { + DEBUGP("successfully registered expect\n"); + } else { + DEBUGP("can't expect_related(expect_reply)\n"); + ip_conntrack_unexpect_related(expect_orig); + return 1; + } + + if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) { + DEBUGP("can't register original keymap\n"); + ip_conntrack_unexpect_related(expect_orig); + ip_conntrack_unexpect_related(expect_reply); + return 1; + } + + if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) { + DEBUGP("can't register reply keymap\n"); + ip_conntrack_unexpect_related(expect_orig); + ip_conntrack_unexpect_related(expect_reply); + ip_ct_gre_keymap_destroy(ct); + return 1; + } + + return 0; +} + +/* inbound packets == from PAC to PNS */ +static int +pptp_inbound_pkt(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + struct PptpControlHeader *ctlh, + union pptp_ctrl_union *pptpReq) +{ + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; + u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL; + + int ret = NF_ACCEPT, rv; + + new_pcid = htons(nat_pptp_info->pns_call_id); + + switch (msg = ntohs(ctlh->messageType)) { + case PPTP_OUT_CALL_REPLY: + pcid = &pptpReq->ocack.peersCallID; + cid = &pptpReq->ocack.callID; + break; + case PPTP_IN_CALL_CONNECT: + pcid = &pptpReq->iccon.peersCallID; + break; + case PPTP_IN_CALL_REQUEST: + /* only need to nat in case PAC is behind NAT box */ + break; + case PPTP_WAN_ERROR_NOTIFY: + pcid = &pptpReq->wanerr.peersCallID; + break; + case PPTP_CALL_DISCONNECT_NOTIFY: + pcid = &pptpReq->disc.callID; + break; + case PPTP_SET_LINK_INFO: + pcid = &pptpReq->setlink.peersCallID; + break; + + default: + DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? + pptp_msg_name[msg]:pptp_msg_name[0]); + /* fall through */ + + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; + } + + /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST, + * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ + + /* mangle packet */ + IP_NF_ASSERT(pcid); + DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", + ntohs(*pcid), ntohs(new_pcid)); + + rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), + sizeof(new_pcid), (char *)&new_pcid, + sizeof(new_pcid)); + if (rv != NF_ACCEPT) + return rv; + + if (new_cid) { + IP_NF_ASSERT(cid); + DEBUGP("altering call id from 0x%04x to 0x%04x\n", + ntohs(*cid), ntohs(new_cid)); + rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), + sizeof(new_cid), + (char *)&new_cid, + sizeof(new_cid)); + if (rv != NF_ACCEPT) + return rv; + } + + /* check for earlier return value of 'switch' above */ + if (ret != NF_ACCEPT) + return ret; + + /* great, at least we don't need to resize packets */ + return NF_ACCEPT; +} + + +extern int __init ip_nat_proto_gre_init(void); +extern void __exit ip_nat_proto_gre_fini(void); + +static int __init init(void) +{ + int ret; + + DEBUGP("%s: registering NAT helper\n", __FILE__); + + ret = ip_nat_proto_gre_init(); + if (ret < 0) + return ret; + + BUG_ON(ip_nat_pptp_hook_outbound); + ip_nat_pptp_hook_outbound = &pptp_outbound_pkt; + + BUG_ON(ip_nat_pptp_hook_inbound); + ip_nat_pptp_hook_inbound = &pptp_inbound_pkt; + + BUG_ON(ip_nat_pptp_hook_exp_gre); + ip_nat_pptp_hook_exp_gre = &pptp_exp_gre; + + BUG_ON(ip_nat_pptp_hook_expectfn); + ip_nat_pptp_hook_expectfn = &pptp_nat_expected; + + printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); + return 0; +} + +static void __exit fini(void) +{ + DEBUGP("cleanup_module\n" ); + + ip_nat_pptp_hook_expectfn = NULL; + ip_nat_pptp_hook_exp_gre = NULL; + ip_nat_pptp_hook_inbound = NULL; + ip_nat_pptp_hook_outbound = NULL; + + ip_nat_proto_gre_fini(); + /* Make sure noone calls it, meanwhile */ + synchronize_net(); + + printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c new file mode 100644 index 0000000..7c12854 --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -0,0 +1,214 @@ +/* + * ip_nat_proto_gre.c - Version 2.0 + * + * NAT protocol helper module for GRE. + * + * GRE is a generic encapsulation protocol, which is generally not very + * suited for NAT, as it has no protocol-specific part as port numbers. + * + * It has an optional key field, which may help us distinguishing two + * connections between the same two hosts. + * + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * + * PPTP is built on top of a modified version of GRE, and has a mandatory + * field called "CallID", which serves us for the same purpose as the key + * field in plain GRE. + * + * Documentation about PPTP can be found in RFC 2637 + * + * (C) 2000-2005 by Harald Welte + * + * Development of this code funded by Astaro AG (http://www.astaro.com/) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); + +#if 0 +#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ + __FUNCTION__, ## args) +#else +#define DEBUGP(x, args...) +#endif + +/* is key in given range between min and max */ +static int +gre_in_range(const struct ip_conntrack_tuple *tuple, + enum ip_nat_manip_type maniptype, + const union ip_conntrack_manip_proto *min, + const union ip_conntrack_manip_proto *max) +{ + u_int32_t key; + + if (maniptype == IP_NAT_MANIP_SRC) + key = tuple->src.u.gre.key; + else + key = tuple->dst.u.gre.key; + + return ntohl(key) >= ntohl(min->gre.key) + && ntohl(key) <= ntohl(max->gre.key); +} + +/* generate unique tuple ... */ +static int +gre_unique_tuple(struct ip_conntrack_tuple *tuple, + const struct ip_nat_range *range, + enum ip_nat_manip_type maniptype, + const struct ip_conntrack *conntrack) +{ + static u_int16_t key; + u_int16_t *keyptr; + unsigned int min, i, range_size; + + if (maniptype == IP_NAT_MANIP_SRC) + keyptr = &tuple->src.u.gre.key; + else + keyptr = &tuple->dst.u.gre.key; + + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { + DEBUGP("%p: NATing GRE PPTP\n", conntrack); + min = 1; + range_size = 0xffff; + } else { + min = ntohl(range->min.gre.key); + range_size = ntohl(range->max.gre.key) - min + 1; + } + + DEBUGP("min = %u, range_size = %u\n", min, range_size); + + for (i = 0; i < range_size; i++, key++) { + *keyptr = htonl(min + key % range_size); + if (!ip_nat_used_tuple(tuple, conntrack)) + return 1; + } + + DEBUGP("%p: no NAT mapping\n", conntrack); + + return 0; +} + +/* manipulate a GRE packet according to maniptype */ +static int +gre_manip_pkt(struct sk_buff **pskb, + unsigned int iphdroff, + const struct ip_conntrack_tuple *tuple, + enum ip_nat_manip_type maniptype) +{ + struct gre_hdr *greh; + struct gre_hdr_pptp *pgreh; + struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); + unsigned int hdroff = iphdroff + iph->ihl*4; + + /* pgreh includes two optional 32bit fields which are not required + * to be there. That's where the magic '8' comes from */ + if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8)) + return 0; + + greh = (void *)(*pskb)->data + hdroff; + pgreh = (struct gre_hdr_pptp *) greh; + + /* we only have destination manip of a packet, since 'source key' + * is not present in the packet itself */ + if (maniptype == IP_NAT_MANIP_DST) { + /* key manipulation is always dest */ + switch (greh->version) { + case 0: + if (!greh->key) { + DEBUGP("can't nat GRE w/o key\n"); + break; + } + if (greh->csum) { + /* FIXME: Never tested this code... */ + *(gre_csum(greh)) = + ip_nat_cheat_check(~*(gre_key(greh)), + tuple->dst.u.gre.key, + *(gre_csum(greh))); + } + *(gre_key(greh)) = tuple->dst.u.gre.key; + break; + case GRE_VERSION_PPTP: + DEBUGP("call_id -> 0x%04x\n", + ntohl(tuple->dst.u.gre.key)); + pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key)); + break; + default: + DEBUGP("can't nat unknown GRE version\n"); + return 0; + break; + } + } + return 1; +} + +/* print out a nat tuple */ +static unsigned int +gre_print(char *buffer, + const struct ip_conntrack_tuple *match, + const struct ip_conntrack_tuple *mask) +{ + unsigned int len = 0; + + if (mask->src.u.gre.key) + len += sprintf(buffer + len, "srckey=0x%x ", + ntohl(match->src.u.gre.key)); + + if (mask->dst.u.gre.key) + len += sprintf(buffer + len, "dstkey=0x%x ", + ntohl(match->src.u.gre.key)); + + return len; +} + +/* print a range of keys */ +static unsigned int +gre_print_range(char *buffer, const struct ip_nat_range *range) +{ + if (range->min.gre.key != 0 + || range->max.gre.key != 0xFFFF) { + if (range->min.gre.key == range->max.gre.key) + return sprintf(buffer, "key 0x%x ", + ntohl(range->min.gre.key)); + else + return sprintf(buffer, "keys 0x%u-0x%u ", + ntohl(range->min.gre.key), + ntohl(range->max.gre.key)); + } else + return 0; +} + +/* nat helper struct */ +static struct ip_nat_protocol gre = { + .name = "GRE", + .protonum = IPPROTO_GRE, + .manip_pkt = gre_manip_pkt, + .in_range = gre_in_range, + .unique_tuple = gre_unique_tuple, + .print = gre_print, + .print_range = gre_print_range, +#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ + defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) + .range_to_nfattr = ip_nat_port_range_to_nfattr, + .nfattr_to_range = ip_nat_port_nfattr_to_range, +#endif +}; + +int __init ip_nat_proto_gre_init(void) +{ + return ip_nat_protocol_register(&gre); +} + +void __exit ip_nat_proto_gre_fini(void) +{ + ip_nat_protocol_unregister(&gre); +} -- cgit v0.10.2 From e674d0f38de6109b59dbe30fba8b296a03229b8e Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Mon, 19 Sep 2005 15:34:40 -0700 Subject: [NETFILTER] ip6tables: remove duplicate code Some IPv6 matches have very similar loops to find IPv6 extension header and we can unify them. This patch introduces ipv6_find_hdr() to do it. I just checked that it can find the target headers in the packet which has dst,hbh,rt,frag,ah,esp headers. Signed-off-by: Yasuyuki Kozakai Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 58c72a5..59f70b3 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -455,6 +455,9 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb, /* Check for an extension */ extern int ip6t_ext_hdr(u8 nexthdr); +/* find specified header and get offset to it */ +extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, + u8 target); #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1cb8adb..2da514b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1955,6 +1955,57 @@ static void __exit fini(void) #endif } +/* + * find specified header up to transport protocol header. + * If found target header, the offset to the header is set to *offset + * and return 0. otherwise, return -1. + * + * Notes: - non-1st Fragment Header isn't skipped. + * - ESP header isn't skipped. + * - The target header may be trancated. + */ +int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) +{ + unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; + u8 nexthdr = skb->nh.ipv6h->nexthdr; + unsigned int len = skb->len - start; + + while (nexthdr != target) { + struct ipv6_opt_hdr _hdr, *hp; + unsigned int hdrlen; + + if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) + return -1; + hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); + if (hp == NULL) + return -1; + if (nexthdr == NEXTHDR_FRAGMENT) { + unsigned short _frag_off, *fp; + fp = skb_header_pointer(skb, + start+offsetof(struct frag_hdr, + frag_off), + sizeof(_frag_off), + &_frag_off); + if (fp == NULL) + return -1; + + if (ntohs(*fp) & ~0x7) + return -1; + hdrlen = 8; + } else if (nexthdr == NEXTHDR_AUTH) + hdrlen = (hp->hdrlen + 2) << 2; + else + hdrlen = ipv6_optlen(hp); + + nexthdr = hp->nexthdr; + len -= hdrlen; + start += hdrlen; + } + + *offset = start; + return 0; +} + EXPORT_SYMBOL(ip6t_register_table); EXPORT_SYMBOL(ip6t_unregister_table); EXPORT_SYMBOL(ip6t_do_table); @@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); EXPORT_SYMBOL(ip6t_register_target); EXPORT_SYMBOL(ip6t_unregister_target); EXPORT_SYMBOL(ip6t_ext_hdr); +EXPORT_SYMBOL(ipv6_find_hdr); module_init(init); module_exit(fini); diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index d5b94f1..dde3779 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c @@ -48,92 +48,21 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ip_auth_hdr *ah = NULL, _ah; + struct ip_auth_hdr *ah, _ah; const struct ip6t_ah *ahinfo = matchinfo; - unsigned int temp; - int len; - u8 nexthdr; unsigned int ptr; unsigned int hdrlen = 0; - /*DEBUGP("IPv6 AH entered\n");*/ - /* if (opt->auth == 0) return 0; - * It does not filled on output */ - - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; - - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_ah header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) - break; - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) - break; - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) - hdrlen = 8; - else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* AH -> evaluate */ - if (nexthdr == NEXTHDR_AUTH) { - temp |= MASK_AH; - break; - } - - - /* set the flag */ - switch (nexthdr) { - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr); - return 0; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if (ptr > skb->len) { - DEBUGP("ipv6_ah: new pointer too large! \n"); - break; - } - } - - /* AH header not found */ - if (temp != MASK_AH) + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0) return 0; - if (len < sizeof(struct ip_auth_hdr)){ + ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); + if (ah == NULL) { *hotdrop = 1; return 0; } - ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); - BUG_ON(ah == NULL); + hdrlen = (ah->hdrlen + 2) << 2; DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); DEBUGP("RES %04X ", ah->reserved); diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 540925e..c450a63 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -63,8 +63,6 @@ match(const struct sk_buff *skb, struct ipv6_opt_hdr _optsh, *oh; const struct ip6t_opts *optinfo = matchinfo; unsigned int temp; - unsigned int len; - u8 nexthdr; unsigned int ptr; unsigned int hdrlen = 0; unsigned int ret = 0; @@ -72,97 +70,25 @@ match(const struct sk_buff *skb, u8 _optlen, *lp = NULL; unsigned int optlen; - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; - - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_opts header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { - break; - } - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* OPTS -> evaluate */ #if HOPBYHOP - if (nexthdr == NEXTHDR_HOP) { - temp |= MASK_HOPOPTS; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) #else - if (nexthdr == NEXTHDR_DEST) { - temp |= MASK_DSTOPTS; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) #endif - break; - } - + return 0; - /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); - return 0; - break; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_opts: new pointer is too large! \n"); - break; - } - } - - /* OPTIONS header not found */ -#if HOPBYHOP - if ( temp != MASK_HOPOPTS ) return 0; -#else - if ( temp != MASK_DSTOPTS ) return 0; -#endif - - if (len < (int)sizeof(struct ipv6_opt_hdr)){ + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL){ *hotdrop = 1; return 0; } - if (len < hdrlen){ + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen){ /* Packet smaller than it's length field */ return 0; } - oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); - BUG_ON(oh == NULL); - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); DEBUGP("len %02X %04X %02X ", diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e39dd23..24bc0cd 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c @@ -48,87 +48,22 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ip_esp_hdr _esp, *eh = NULL; + struct ip_esp_hdr _esp, *eh; const struct ip6t_esp *espinfo = matchinfo; - unsigned int temp; - int len; - u8 nexthdr; unsigned int ptr; /* Make sure this isn't an evil packet */ /*DEBUGP("ipv6_esp entered \n");*/ - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; - - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - int hdrlen; - - DEBUGP("ipv6_esp header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) - break; - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - temp |= MASK_ESP; - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) - hdrlen = 8; - else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* set the flag */ - switch (nexthdr) { - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr); - return 0; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if (ptr > skb->len) { - DEBUGP("ipv6_esp: new pointer too large! \n"); - break; - } - } - - /* ESP header not found */ - if (temp != MASK_ESP) + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0) return 0; - if (len < sizeof(struct ip_esp_hdr)) { + eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); + if (eh == NULL) { *hotdrop = 1; return 0; } - eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); - BUG_ON(eh == NULL); - DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); return (eh != NULL) diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 4bfa30a..085d5f8 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c @@ -48,90 +48,18 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct frag_hdr _frag, *fh = NULL; + struct frag_hdr _frag, *fh; const struct ip6t_frag *fraginfo = matchinfo; - unsigned int temp; - int len; - u8 nexthdr; unsigned int ptr; - unsigned int hdrlen = 0; - - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; - - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_frag header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { - break; - } - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* FRAG -> evaluate */ - if (nexthdr == NEXTHDR_FRAGMENT) { - temp |= MASK_FRAGMENT; - break; - } - - - /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr); - return 0; - break; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_frag: new pointer too large! \n"); - break; - } - } - - /* FRAG header not found */ - if ( temp != MASK_FRAGMENT ) return 0; - - if (len < sizeof(struct frag_hdr)){ - *hotdrop = 1; - return 0; - } - fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); - BUG_ON(fh == NULL); + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0) + return 0; + + fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); + if (fh == NULL){ + *hotdrop = 1; + return 0; + } DEBUGP("INFO %04X ", fh->frag_off); DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 27f3650..1d09485 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c @@ -63,8 +63,6 @@ match(const struct sk_buff *skb, struct ipv6_opt_hdr _optsh, *oh; const struct ip6t_opts *optinfo = matchinfo; unsigned int temp; - unsigned int len; - u8 nexthdr; unsigned int ptr; unsigned int hdrlen = 0; unsigned int ret = 0; @@ -72,97 +70,25 @@ match(const struct sk_buff *skb, u8 _optlen, *lp = NULL; unsigned int optlen; - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; - - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_opts header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { - break; - } - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* OPTS -> evaluate */ #if HOPBYHOP - if (nexthdr == NEXTHDR_HOP) { - temp |= MASK_HOPOPTS; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) #else - if (nexthdr == NEXTHDR_DEST) { - temp |= MASK_DSTOPTS; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) #endif - break; - } - + return 0; - /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); - return 0; - break; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_opts: new pointer is too large! \n"); - break; - } - } - - /* OPTIONS header not found */ -#if HOPBYHOP - if ( temp != MASK_HOPOPTS ) return 0; -#else - if ( temp != MASK_DSTOPTS ) return 0; -#endif - - if (len < (int)sizeof(struct ipv6_opt_hdr)){ + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL){ *hotdrop = 1; return 0; } - if (len < hdrlen){ + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen){ /* Packet smaller than it's length field */ return 0; } - oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); - BUG_ON(oh == NULL); - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); DEBUGP("len %02X %04X %02X ", diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 2bb6700..beb2fd5 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -50,98 +50,29 @@ match(const struct sk_buff *skb, unsigned int protoff, int *hotdrop) { - struct ipv6_rt_hdr _route, *rh = NULL; + struct ipv6_rt_hdr _route, *rh; const struct ip6t_rt *rtinfo = matchinfo; unsigned int temp; - unsigned int len; - u8 nexthdr; unsigned int ptr; unsigned int hdrlen = 0; unsigned int ret = 0; struct in6_addr *ap, _addr; - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0) + return 0; - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_rt header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { - break; - } - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* ROUTING -> evaluate */ - if (nexthdr == NEXTHDR_ROUTING) { - temp |= MASK_ROUTING; - break; - } - - - /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr); - return 0; - break; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_rt: new pointer is too large! \n"); - break; - } - } - - /* ROUTING header not found */ - if ( temp != MASK_ROUTING ) return 0; - - if (len < (int)sizeof(struct ipv6_rt_hdr)){ + rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); + if (rh == NULL){ *hotdrop = 1; return 0; } - if (len < hdrlen){ + hdrlen = ipv6_optlen(rh); + if (skb->len - ptr < hdrlen){ /* Pcket smaller than its length field */ return 0; } - rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); - BUG_ON(rh == NULL); - DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); DEBUGP("TYPE %04X ", rh->type); DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); -- cgit v0.10.2 From a41bc00234a0a2ccaa99a194341ae108ae17ddc8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 19 Sep 2005 15:35:31 -0700 Subject: [NETFILTER]: Rename misnamed function Both __ip_conntrack_expect_find and ip_conntrack_expect_find_get take a reference to the expectation, the difference is that callers of __ip_conntrack_expect_find must hold ip_conntrack_lock. Signed-off-by: Patrick McHardy Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 2df446c..bace72a 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -384,7 +384,7 @@ extern struct ip_conntrack_expect * __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); extern struct ip_conntrack_expect * -ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple); +ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); extern struct ip_conntrack_tuple_hash * __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index f8cd8e4..c1f82e0 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) /* Just find a expectation corresponding to a tuple. */ struct ip_conntrack_expect * -ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple) +ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) { struct ip_conntrack_expect *i; diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 15aef35..b08a432 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1270,7 +1270,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = ip_conntrack_expect_find_get(&tuple); + exp = ip_conntrack_expect_find(&tuple); if (!exp) return -ENOENT; @@ -1318,7 +1318,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = ip_conntrack_expect_find_get(&tuple); + exp = ip_conntrack_expect_find(&tuple); if (!exp) return -ENOENT; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index ae3e3e6..d3c7808 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -993,11 +993,11 @@ EXPORT_SYMBOL(ip_ct_refresh_acct); EXPORT_SYMBOL(ip_conntrack_expect_alloc); EXPORT_SYMBOL(ip_conntrack_expect_put); -EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get); +EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); +EXPORT_SYMBOL_GPL(ip_conntrack_expect_find); EXPORT_SYMBOL(ip_conntrack_expect_related); EXPORT_SYMBOL(ip_conntrack_unexpect_related); EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); -EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); EXPORT_SYMBOL_GPL(ip_ct_unlink_expect); EXPORT_SYMBOL(ip_conntrack_tuple_taken); -- cgit v0.10.2 From 8922bc93aa78a202c2b68b2de19b71329cb321e1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 19 Sep 2005 15:35:57 -0700 Subject: [NETFILTER]: Export ip_nat_port_{nfattr_to_range,range_to_nfattr} Those exports are needed by the PPTP helper following in the next couple of changes. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 1adedb7..c3ea891 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -578,6 +578,8 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range) return ret; } +EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range); +EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr); #endif int __init ip_nat_init(void) -- cgit v0.10.2 From 2cf655cd65888e9fed0803d77e9e4f7d1db674cc Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Mon, 19 Sep 2005 15:39:32 -0700 Subject: [WAN] hdlc_cisco: Fix regression introduced by skb->tail changes. The following commit breaks cisco mode with my WAN drivers: author David S. Miller Tue, 28 Jun 2005 22:25:31 +0000 (15:25 -0700) commit 689be43945e9ca7dd704522e55af1b8a73a994d3 "[NET]: Remove gratuitous use of skb->tail in network drivers." The following patch fixes it - please apply (cisco_hard_header does skb_push(4 bytes)). Signed-off-by: David S. Miller diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 48c03c1..a01efa6 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, } skb_reserve(skb, 4); cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); - data = (cisco_packet*)skb->data; + data = (cisco_packet*)(skb->data + 4); data->type = htonl(type); data->par1 = htonl(par1); -- cgit v0.10.2 From 3c3f8f25c177e4f9e4e00bcc1b90b28b1be37937 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 19 Sep 2005 15:41:28 -0700 Subject: [8021Q]: Add endian annotations. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 17d0c0d..eef0876 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -42,8 +42,8 @@ struct hlist_node; struct vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ - unsigned short h_vlan_proto; /* Should always be 0x8100 */ - unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + __be16 h_vlan_proto; /* Should always be 0x8100 */ + __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */ unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ }; @@ -55,8 +55,8 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) } struct vlan_hdr { - unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ - unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ + __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */ + __be16 h_vlan_encapsulated_proto; /* packet type ID field (or len) */ }; #define VLAN_VID_MASK 0xfff diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 145f5cd..b748648 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -120,7 +120,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, unsigned short vid; struct net_device_stats *stats; unsigned short vlan_TCI; - unsigned short proto; + __be16 proto; /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ vlan_TCI = ntohs(vhdr->h_vlan_TCI); -- cgit v0.10.2 From e14c3caf605dfd29bd1aac3097e39db94afc9f07 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 19 Sep 2005 18:18:38 -0700 Subject: [TCP]: Handle SACK'd packets properly in tcp_fragment(). The problem is that we're now calling tcp_fragment() in a context where the packets might be marked as SACKED_ACKED or SACKED_RETRANS. This was not possible before as you never retransmitted packets that are so marked. Because of this, we need to adjust sacked_out and retrans_out in tcp_fragment(). This is exactly what the following patch does. We also need to preserve the SACKED_ACKED/SACKED_RETRANS marking if they exist. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b018e31..5dd6dd7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -461,9 +461,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss flags = TCP_SKB_CB(skb)->flags; TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); TCP_SKB_CB(buff)->flags = flags; - TCP_SKB_CB(buff)->sacked = - (TCP_SKB_CB(skb)->sacked & - (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL)); + TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked; TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { @@ -501,6 +499,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss tcp_skb_pcount(buff); tp->packets_out -= diff; + + if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) + tp->sacked_out -= diff; + if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) + tp->retrans_out -= diff; + if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { tp->lost_out -= diff; tp->left_out -= diff; -- cgit v0.10.2 From 6d1cfe3f1752f17e297df60c8bcc6cd6e0a58449 Mon Sep 17 00:00:00 2001 From: Mark J Cox Date: Mon, 19 Sep 2005 17:55:30 -0700 Subject: [PATCH] raw_sendmsg DoS on 2.6 Fix unchecked __get_user that could be tricked into generating a memory read on an arbitrary address. The result of the read is not returned directly but you may be able to divine some information about it, or use the read to cause a crash on some architectures by reading hardware state. CAN-2004-2492. Fix from Al Viro, ack from Dave Miller. Signed-off-by: Linus Torvalds diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 304bb0a..4b0d7e4 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -361,7 +361,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (type && code) { get_user(fl->fl_icmp_type, type); - __get_user(fl->fl_icmp_code, code); + get_user(fl->fl_icmp_code, code); probed = 1; } break; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5aa3691..a1265a3 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (type && code) { get_user(fl->fl_icmp_type, type); - __get_user(fl->fl_icmp_code, code); + get_user(fl->fl_icmp_code, code); probed = 1; } break; -- cgit v0.10.2 From f805fbdaacf4367ce566743a665622387768ac0d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 19 Sep 2005 19:54:29 -0700 Subject: Make fsnotify possibly work better for the inode removal case Checking i_nlink is dubious, but the alternatives look even less appetizing. Signed-off-by: Linus Torvalds diff --git a/fs/dcache.c b/fs/dcache.c index 7376b612..fb10386 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -102,7 +102,8 @@ static inline void dentry_iput(struct dentry * dentry) list_del_init(&dentry->d_alias); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); - fsnotify_inoderemove(inode); + if (!inode->i_nlink) + fsnotify_inoderemove(inode); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else -- cgit v0.10.2 From ff171d8f66a7fe1a000e610e9de11224749f9a22 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 19 Sep 2005 19:56:06 -0700 Subject: [SPARC64]: Handle little-endian unaligned loads/stores correctly. Because we use byte loads/stores to cons up the value in and out of registers, we can't expect the ASI endianness setting to take care of this for us. So do it by hand. This case is triggered by drivers/block/aoe/aoecmd.c in the ataid_complete() function where it goes: /* word 100: number lba48 sectors */ ssize = le64_to_cpup((__le64 *) &id[100<<1]); This &id[100<<1] address is 4 byte, rather than 8 byte aligned, thus triggering the unaligned exception. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S index cbb4058..da48400 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc64/kernel/una_asm.S @@ -17,7 +17,7 @@ kernel_unaligned_trap_fault: __do_int_store: rd %asi, %o4 wr %o3, 0, %asi - ldx [%o2], %g3 + mov %o2, %g3 cmp %o1, 2 be,pn %icc, 2f cmp %o1, 4 diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index da9739f..42718f6 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size, unsigned long *saddr, int is_signed, int asi); extern void __do_int_store(unsigned long *dst_addr, int size, - unsigned long *src_val, int asi); + unsigned long src_val, int asi); static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, - struct pt_regs *regs, int asi) + struct pt_regs *regs, int asi, int orig_asi) { unsigned long zero = 0; - unsigned long *src_val = &zero; + unsigned long *src_val_p = &zero; + unsigned long src_val; if (size == 16) { size = 8; @@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | (unsigned)fetch_reg(reg_num + 1, regs); } else if (reg_num) { - src_val = fetch_reg_addr(reg_num, regs); + src_val_p = fetch_reg_addr(reg_num, regs); + } + src_val = *src_val_p; + if (unlikely(asi != orig_asi)) { + switch (size) { + case 2: + src_val = swab16(src_val); + break; + case 4: + src_val = swab32(src_val); + break; + case 8: + src_val = swab64(src_val); + break; + case 16: + default: + BUG(); + break; + }; } __do_int_store(dst_addr, size, src_val, asi); } @@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u kernel_mna_trap_fault(); } else { unsigned long addr; + int orig_asi, asi; addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); @@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u regs->tpc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]); #endif + orig_asi = asi = decode_asi(insn, regs); + switch (asi) { + case ASI_NL: + case ASI_AIUPL: + case ASI_AIUSL: + case ASI_PL: + case ASI_SL: + case ASI_PNFL: + case ASI_SNFL: + asi &= ~0x08; + break; + }; switch (dir) { case load: do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), size, (unsigned long *) addr, - decode_signedness(insn), - decode_asi(insn, regs)); + decode_signedness(insn), asi); + if (unlikely(asi != orig_asi)) { + unsigned long val_in = *(unsigned long *) addr; + switch (size) { + case 2: + val_in = swab16(val_in); + break; + case 4: + val_in = swab32(val_in); + break; + case 8: + val_in = swab64(val_in); + break; + case 16: + default: + BUG(); + break; + }; + *(unsigned long *) addr = val_in; + } break; case store: do_int_store(((insn>>25)&0x1f), size, (unsigned long *) addr, regs, - decode_asi(insn, regs)); + asi, orig_asi); break; default: -- cgit v0.10.2 From e0487992ce1dd7ae7da9c6aabdb19570bb95432b Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Mon, 19 Sep 2005 19:57:36 -0700 Subject: [BYTEORDER]: Document alignment and byteorder macros This patch comments the fact that although passing le64_to_cpup et al. is within the intended use of the byteorder macros, using get_unaligned is the recommended way to go. Signed-off-by: Ed L. Cashin Signed-off-by: David S. Miller diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h index 5fde6f4..04bd756 100644 --- a/include/linux/byteorder/generic.h +++ b/include/linux/byteorder/generic.h @@ -5,6 +5,10 @@ * linux/byteorder_generic.h * Generic Byte-reordering support * + * The "... p" macros, like le64_to_cpup, can be used with pointers + * to unaligned data, but there will be a performance penalty on + * some architectures. Use get_unaligned for unaligned data. + * * Francois-Rene Rideau 19970707 * gathered all the good ideas from all asm-foo/byteorder.h into one file, * cleaned them up. -- cgit v0.10.2 From 676d55ae30ea3b688f0386f70553489f25f24d55 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 19 Sep 2005 20:00:41 -0700 Subject: Linux v2.6.14-rc2 Avast, ye scurvy land-lubbers! Time to try out a new release. Arrr! diff --git a/Makefile b/Makefile index 4e0d7c6..8cf6bec 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 14 -EXTRAVERSION =-rc1 +EXTRAVERSION =-rc2 NAME=Affluent Albatross # *DOCUMENTATION* -- cgit v0.10.2 From 6a9b490d5fd7f23c5bcd75f970e01633ad3136e3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 19 Sep 2005 20:11:57 -0700 Subject: [SPARC64]: Move DCACHE_ALIASING_POSSIBLE define to asm/page.h This showed that arch/sparc64/kernel/ptrace.c was not getting the define properly, and thus the code protected by this ifdef was never actually compiled before. So fix that too. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 23ad839..5efbff9 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -30,6 +30,7 @@ #include #include #include +#include /* Returning from ptrace is a bit tricky because the syscall return * low level code assumes any value returned which is negative and @@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, * is mapped to in the user's address space, we can skip the * D-cache flush. */ - if ((uaddr ^ kaddr) & (1UL << 13)) { + if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { unsigned long start = __pa(kaddr); unsigned long end = start + len; if (tlb_type == spitfire) { for (; start < end; start += 32) - spitfire_put_dcache_tag(va & 0x3fe0, 0x0); + spitfire_put_dcache_tag(start & 0x3fe0, 0x0); } else { for (; start < end; start += 32) __asm__ __volatile__( "stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (va), + : "r" (start), "i" (ASI_DCACHE_INVALIDATE)); } } diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h index 51b26e81..ededd26 100644 --- a/include/asm-sparc64/cacheflush.h +++ b/include/asm-sparc64/cacheflush.h @@ -4,13 +4,6 @@ #include #include -/* Flushing for D-cache alias handling is only needed if - * the page size is smaller than 16K. - */ -#if PAGE_SHIFT < 14 -#define DCACHE_ALIASING_POSSIBLE -#endif - #ifndef __ASSEMBLY__ #include diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h index 4c10984..c393f81 100644 --- a/include/asm-sparc64/ide.h +++ b/include/asm-sparc64/ide.h @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef MAX_HWIFS # ifdef CONFIG_BLK_DEV_IDEPCI diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index c9f8ef2..7f8d764 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h @@ -21,6 +21,13 @@ #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +/* Flushing for D-cache alias handling is only needed if + * the page size is smaller than 16K. + */ +#if PAGE_SHIFT < 14 +#define DCACHE_ALIASING_POSSIBLE +#endif + #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h index b9b1914..a96067c 100644 --- a/include/asm-sparc64/pgalloc.h +++ b/include/asm-sparc64/pgalloc.h @@ -10,6 +10,7 @@ #include #include #include +#include /* Page table allocation/freeing. */ #ifdef CONFIG_SMP -- cgit v0.10.2 From eed8b2dee7cff46dd4bf5b82dc53465d229162ba Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Tue, 20 Sep 2005 14:19:30 +0100 Subject: NTFS: More runlist handling fixes from Richard Russon and myself. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index e2665d0..061b5ff 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -158,17 +158,21 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst, BUG_ON(!dst); BUG_ON(!src); - if ((dst->lcn < 0) || (src->lcn < 0)) { /* Are we merging holes? */ - if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE) - return TRUE; + /* We can merge unmapped regions even if they are misaligned. */ + if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED)) + return TRUE; + /* If the runs are misaligned, we cannot merge them. */ + if ((dst->vcn + dst->length) != src->vcn) return FALSE; - } - if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ - return FALSE; - if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ - return FALSE; - - return TRUE; + /* If both runs are non-sparse and contiguous, we can merge them. */ + if ((dst->lcn >= 0) && (src->lcn >= 0) && + ((dst->lcn + dst->length) == src->lcn)) + return TRUE; + /* If we are merging two holes, we can merge them. */ + if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE)) + return TRUE; + /* Cannot merge. */ + return FALSE; } /** @@ -214,14 +218,15 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src) static inline runlist_element *ntfs_rl_append(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL right; /* Right end of @src needs merging. */ - int marker; /* End of the inserted runs. */ + BOOL right = FALSE; /* Right end of @src needs merging. */ + int marker; /* End of the inserted runs. */ BUG_ON(!dst); BUG_ON(!src); /* First, check if the right hand end needs merging. */ - right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); + if ((loc + 1) < dsize) + right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); /* Space required: @dst size + @src size, less one if we merged. */ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); @@ -377,20 +382,21 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { BOOL left = FALSE; /* Left end of @src needs merging. */ - BOOL right; /* Right end of @src needs merging. */ + BOOL right = FALSE; /* Right end of @src needs merging. */ int tail; /* Start of tail of @dst. */ int marker; /* End of the inserted runs. */ BUG_ON(!dst); BUG_ON(!src); - /* First, merge the left and right ends, if necessary. */ - right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); + /* First, see if the left and right ends need merging. */ + if ((loc + 1) < dsize) + right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); if (loc > 0) left = ntfs_are_rl_mergeable(dst + loc - 1, src); /* * Allocate some space. We will need less if the left, right, or both - * ends were merged. + * ends get merged. */ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); if (IS_ERR(dst)) @@ -399,21 +405,26 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, * We are guaranteed to succeed from here so can start modifying the * original runlists. */ + + /* First, merge the left and right ends, if necessary. */ if (right) __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); if (left) __ntfs_rl_merge(dst + loc - 1, src); /* - * First run of @dst that needs to be moved out of the way to make - * space for the runs to be copied from @src, i.e. the first run of the - * tail of @dst. + * Offset of the tail of @dst. This needs to be moved out of the way + * to make space for the runs to be copied from @src, i.e. the first + * run of the tail of @dst. + * Nominally, @tail equals @loc + 1, i.e. location, skipping the + * replaced run. However, if @right, then one of @dst's runs is + * already merged into @src. */ tail = loc + right + 1; /* * First run after the @src runs that have been inserted, i.e. where * the tail of @dst needs to be moved to. - * Nominally, marker equals @loc + @ssize, i.e. location + number of - * runs in @src). However, if @left, then the first run in @src has + * Nominally, @marker equals @loc + @ssize, i.e. location + number of + * runs in @src. However, if @left, then the first run in @src has * been merged with one in @dst. */ marker = loc + ssize - left; -- cgit v0.10.2 From 9506057fca54464f3291b62156e6cd907c4cbc95 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Sep 2005 16:20:49 +0100 Subject: [ARM] 2924/3: taglist - postfix section with .init for `make buildcheck` Patch from Ben Dooks The `make buildcheck` is erroneously reporting that the taglist is referencing items in the .init section as it is not itself postfixed with .init Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index ad2d66c..350b53b 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -29,7 +29,7 @@ SECTIONS *(.arch.info) __arch_info_end = .; __tagtable_begin = .; - *(.taglist) + *(.taglist.init) __tagtable_end = .; . = ALIGN(16); __setup_start = .; diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h index adcbd79..a4b3ebf 100644 --- a/include/asm-arm/setup.h +++ b/include/asm-arm/setup.h @@ -171,7 +171,7 @@ struct tagtable { int (*parse)(const struct tag *); }; -#define __tag __attribute_used__ __attribute__((__section__(".taglist"))) +#define __tag __attribute_used__ __attribute__((__section__(".taglist.init"))) #define __tagtable(tag, fn) \ static struct tagtable __tagtable_##fn __tag = { tag, fn } -- cgit v0.10.2 From 58dd48a6575d3ba86ba659eb8c6fc23246783fba Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 20 Sep 2005 16:21:42 +0100 Subject: [ARM] 2922/1: compile fix for shark Patch from Vincent Sanders Shark platform fails to build with gcc 4 because of a bad lvalue assignement Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c index 7f6f5db..465c54b 100644 --- a/arch/arm/boot/compressed/ofw-shark.c +++ b/arch/arm/boot/compressed/ofw-shark.c @@ -256,5 +256,5 @@ asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) temp[11]='\0'; mem_len = OF_getproplen(o,phandle, temp); OF_getprop(o,phandle, temp, buffer, mem_len); - (unsigned char) pointer[32] = ((unsigned char *) buffer)[mem_len-2]; + * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2]; } -- cgit v0.10.2 From bfe6815e0465035d013b2b676444376fe2b3716e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Sep 2005 16:25:12 +0100 Subject: [ARM] 2925/3: earlyparam - postfix section with .init for `make buildcheck` Patch from Ben Dooks The `make buildcheck` is erroneously reporting that the earlyparam list is referencing items in the .init section as it is not itself postfixed with .init Also, as per rmk's suggestion, rename the __early_param to .early_param to bring it into line with everything else Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 350b53b..47423aa 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -36,7 +36,7 @@ SECTIONS *(.init.setup) __setup_end = .; __early_begin = .; - *(__early_param) + *(.early_param.init) __early_end = .; __initcall_start = .; *(.initcall1.init) diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h index a4b3ebf..ea3ed24 100644 --- a/include/asm-arm/setup.h +++ b/include/asm-arm/setup.h @@ -213,6 +213,6 @@ struct early_params { #define __early_param(name,fn) \ static struct early_params __early_##fn __attribute_used__ \ -__attribute__((__section__("__early_param"))) = { name, fn } +__attribute__((__section__(".early_param.init"))) = { name, fn } #endif -- cgit v0.10.2 From 02b7dd1244aab9267ae4078e1ad6a2fdaabeb6ed Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Sep 2005 16:35:03 +0100 Subject: [ARM] 2926/1: .proc.info - postfix section with .init for `make buildcheck` Patch from Ben Dooks The `make buildcheck` is erroneously reporting that the .proc.info list is referencing items in the .init section as it is not itself postfixed with .init Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 47423aa..420b8d0 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -23,7 +23,7 @@ SECTIONS *(.init.text) _einittext = .; __proc_info_begin = .; - *(.proc.info) + *(.proc.info.init) __proc_info_end = .; __arch_info_begin = .; *(.arch.info) diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 1d739d2..82ec954 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -509,7 +509,7 @@ cpu_arm1020_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm1020_proc_info,#object __arm1020_proc_info: diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 9b72566..7375fe9 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -491,7 +491,7 @@ cpu_arm1020e_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm1020e_proc_info,#object __arm1020e_proc_info: diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 37b70fa..6ca6390 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -473,7 +473,7 @@ cpu_arm1022_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm1022_proc_info,#object __arm1022_proc_info: diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 931b690..10317e4 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -469,7 +469,7 @@ cpu_arm1026_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm1026_proc_info,#object __arm1026_proc_info: diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index d0f1bbb..8e7e1e7 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -332,7 +332,7 @@ cpu_arm710_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm6_proc_info, #object __arm6_proc_info: diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index c69c9de..a13e018 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -222,7 +222,7 @@ cpu_arm720_name: * See linux/include/asm-arm/procinfo.h for a definition of this structure. */ - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm710_proc_info, #object __arm710_proc_info: diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 0f490a0..d165138 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -452,7 +452,7 @@ cpu_arm920_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm920_proc_info,#object __arm920_proc_info: diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 62bc34a..23b8ed9 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -456,7 +456,7 @@ cpu_arm922_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm922_proc_info,#object __arm922_proc_info: diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index ee49aa2..ee95c52 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -521,7 +521,7 @@ cpu_arm925_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm925_proc_info,#object __arm925_proc_info: diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index bb95cc9..7d042dc 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -471,7 +471,7 @@ cpu_arm926_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __arm926_proc_info,#object __arm926_proc_info: diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 34f7e7d..bd330c4 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -249,7 +249,7 @@ cpu_sa110_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __sa110_proc_info,#object __sa110_proc_info: diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index ca14f80..91b8912 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -280,7 +280,7 @@ cpu_sa1110_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __sa1100_proc_info,#object __sa1100_proc_info: diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index eb34823..caf3b19 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -240,7 +240,7 @@ cpu_elf_name: .size cpu_elf_name, . - cpu_elf_name .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr /* * Match any ARMv6 processor core. diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index b88de270..861b3594 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -578,7 +578,7 @@ cpu_pxa270_name: .align - .section ".proc.info", #alloc, #execinstr + .section ".proc.info.init", #alloc, #execinstr .type __80200_proc_info,#object __80200_proc_info: -- cgit v0.10.2 From 9d0fd1eb8a3c19f3ede5418540b3c9f64fac4b86 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Sep 2005 16:45:20 +0100 Subject: [ARM] 2927/1: .arch.info - postfix section with .init for `make buildcheck` Patch from Ben Dooks The `make buildcheck` is erroneously reporting that the .arch.info list is referencing items in the .init section as it is not itself postfixed with .init Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 420b8d0..08e58ec 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -26,7 +26,7 @@ SECTIONS *(.proc.info.init) __proc_info_end = .; __arch_info_begin = .; - *(.arch.info) + *(.arch.info.init) __arch_info_end = .; __tagtable_begin = .; *(.taglist.init) diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index 56c6bf4..4fa9508 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h @@ -50,7 +50,7 @@ struct machine_desc { */ #define MACHINE_START(_type,_name) \ const struct machine_desc __mach_desc_##_type \ - __attribute__((__section__(".arch.info"))) = { \ + __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_##_type, \ .name = _name, -- cgit v0.10.2 From 5fe10ab19046d84f3fd243436cbd5fa01019e809 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 20 Sep 2005 17:24:33 +0100 Subject: [ARM] 2928/1: S3C2410 - make machine init code static Patch from Ben Dooks This code is not being exported, declare it static Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index f87aa0b..7c05f27 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -12,6 +12,7 @@ * * Modifications: * 02-May-2005 BJD Copied from mach-bast.c + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -232,7 +233,7 @@ static struct s3c24xx_board anubis_board __initdata = { .clocks_count = ARRAY_SIZE(anubis_clocks) }; -void __init anubis_map_io(void) +static void __init anubis_map_io(void) { /* initialise the clocks */ diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 1a3367d..ed1f07d 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -31,6 +31,7 @@ * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s * 25-Jul-2005 BJD Removed ASIX static mappings * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -428,7 +429,7 @@ static struct s3c24xx_board bast_board __initdata = { .clocks_count = ARRAY_SIZE(bast_clocks) }; -void __init bast_map_io(void) +static void __init bast_map_io(void) { /* initialise the clocks */ diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 6ff1889..fb3cb012 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -24,6 +24,7 @@ * 10-Jan-2005 BJD Removed include of s3c2410.h * 14-Jan-2005 BJD Added clock init * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -147,7 +148,7 @@ static struct s3c24xx_board h1940_board __initdata = { .devices_count = ARRAY_SIZE(h1940_devices) }; -void __init h1940_map_io(void) +static void __init h1940_map_io(void) { s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); s3c24xx_init_clocks(0); @@ -155,13 +156,13 @@ void __init h1940_map_io(void) s3c24xx_set_board(&h1940_board); } -void __init h1940_init_irq(void) +static void __init h1940_init_irq(void) { s3c24xx_init_irq(); } -void __init h1940_init(void) +static void __init h1940_init(void) { set_s3c2410fb_info(&h1940_lcdcfg); } diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 66bf5bb..5c0f2b0 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -97,7 +97,7 @@ static struct s3c24xx_board n30_board __initdata = { .devices_count = ARRAY_SIZE(n30_devices) }; -void __init n30_map_io(void) +static void __init n30_map_io(void) { s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); s3c24xx_init_clocks(0); @@ -105,14 +105,14 @@ void __init n30_map_io(void) s3c24xx_set_board(&n30_board); } -void __init n30_init_irq(void) +static void __init n30_init_irq(void) { s3c24xx_init_irq(); } /* GPB3 is the line that controls the pull-up for the USB D+ line */ -void __init n30_init(void) +static void __init n30_init(void) { s3c_device_i2c.dev.platform_data = &n30_i2ccfg; diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c index d24c242..c22f821 100644 --- a/arch/arm/mach-s3c2410/mach-nexcoder.c +++ b/arch/arm/mach-s3c2410/mach-nexcoder.c @@ -136,7 +136,7 @@ static void __init nexcoder_sensorboard_init(void) s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN } -void __init nexcoder_map_io(void) +static void __init nexcoder_map_io(void) { s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c index d901ed4..ad1459e 100644 --- a/arch/arm/mach-s3c2410/mach-otom.c +++ b/arch/arm/mach-s3c2410/mach-otom.c @@ -105,7 +105,7 @@ static struct s3c24xx_board otom11_board __initdata = { }; -void __init otom11_map_io(void) +static void __init otom11_map_io(void) { s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index a73d61c..22d9e07 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c @@ -16,6 +16,7 @@ * 14-Jan-2005 BJD Added new clock init * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA * 14-Mar-2005 BJD Fixed __iomem warnings + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -108,7 +109,7 @@ static struct s3c24xx_board rx3715_board __initdata = { .devices_count = ARRAY_SIZE(rx3715_devices) }; -void __init rx3715_map_io(void) +static void __init rx3715_map_io(void) { s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); s3c24xx_init_clocks(16934000); @@ -116,7 +117,7 @@ void __init rx3715_map_io(void) s3c24xx_set_board(&rx3715_board); } -void __init rx3715_init_irq(void) +static void __init rx3715_init_irq(void) { s3c24xx_init_irq(); } diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 67e903a..2eda55a 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -28,6 +28,7 @@ * Ben Dooks * * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 20-Sep-2005 BJD Added static to non-exported items * ***********************************************************************/ @@ -97,7 +98,7 @@ static struct s3c24xx_board smdk2410_board __initdata = { .devices_count = ARRAY_SIZE(smdk2410_devices) }; -void __init smdk2410_map_io(void) +static void __init smdk2410_map_io(void) { s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); s3c24xx_init_clocks(0); @@ -105,7 +106,7 @@ void __init smdk2410_map_io(void) s3c24xx_set_board(&smdk2410_board); } -void __init smdk2410_init_irq(void) +static void __init smdk2410_init_irq(void) { s3c24xx_init_irq(); } diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index 3575221..722ef46 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c @@ -18,6 +18,7 @@ * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa * 10-Mar-2005 LCVR Replaced S3C2410_VA by S3C24XX_VA * 14-Mar-2005 BJD void __iomem fixes + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -98,7 +99,7 @@ static struct s3c24xx_board smdk2440_board __initdata = { .devices_count = ARRAY_SIZE(smdk2440_devices) }; -void __init smdk2440_map_io(void) +static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); s3c24xx_init_clocks(16934400); @@ -106,7 +107,7 @@ void __init smdk2440_map_io(void) s3c24xx_set_board(&smdk2440_board); } -void __init smdk2440_machine_init(void) +static void __init smdk2440_machine_init(void) { /* Configure the LEDs (even if we have no LED support)*/ diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 8f9ab28..663a7f9 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -28,6 +28,7 @@ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA * 14-Mar-2006 BJD void __iomem fixes * 22-Jun-2006 BJD Added DM9000 platform information + * 20-Sep-2005 BJD Added static to non-exported items */ #include @@ -347,7 +348,7 @@ static void vr1000_power_off(void) s3c2410_gpio_setpin(S3C2410_GPB9, 1); } -void __init vr1000_map_io(void) +static void __init vr1000_map_io(void) { /* initialise clock sources */ -- cgit v0.10.2 From 840ff6a4f6174d7fe19c206b5f36ff64123a2f45 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 20 Sep 2005 17:52:13 +0100 Subject: [ARM] Prevent deadlock in page fault handler As per x86, we may deadlock while trying to get the mmap semaphore. Implement the same fix, which allows (eg) recursive faults to cause an oops instead of deadlocking. Signed-off-by: Russell King diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 0b6c4db..4a884ba 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -233,7 +233,17 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (in_interrupt() || !mm) goto no_context; - down_read(&mm->mmap_sem); + /* + * As per x86, we may deadlock here. However, since the kernel only + * validly references user space from well defined areas of the code, + * we can bug out early if this is from code which shouldn't. + */ + if (!down_read_trylock(&mm->mmap_sem)) { + if (!user_mode(regs) && !search_exception_tables(regs->ARM_pc)) + goto no_context; + down_read(&mm->mmap_sem); + } + fault = __do_page_fault(mm, addr, fsr, tsk); up_read(&mm->mmap_sem); -- cgit v0.10.2 From 8d2cae0651502028bf64844508ab18528bbd65c2 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 20 Sep 2005 10:52:04 -0700 Subject: [PATCH] IPoIB: Don't flush workqueue from within workqueue ipoib_mcast_restart_task() is always called from within the single-threaded IPoIB workqueue, so flushing the workqueue from within the function can lead to a recursion overflow. But since we're running in a single-threaded workqueue, we're already synchronized against other items in the workqueue, so just get rid of the flush in ipoib_mcast_restart_task(). Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index bea960b..4ea1c1c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -257,7 +257,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, void ipoib_mcast_restart_task(void *dev_ptr); int ipoib_mcast_start_thread(struct net_device *dev); -int ipoib_mcast_stop_thread(struct net_device *dev); +int ipoib_mcast_stop_thread(struct net_device *dev, int flush); void ipoib_mcast_dev_down(struct net_device *dev); void ipoib_mcast_dev_flush(struct net_device *dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index ef0e389..f744009 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -432,7 +432,7 @@ int ipoib_ib_dev_down(struct net_device *dev) flush_workqueue(ipoib_workqueue); } - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 1); /* * Flush the multicast groups first so we stop any multicast joins. The @@ -599,7 +599,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) ipoib_dbg(priv, "cleaning up ib_dev\n"); - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 1); /* Delete the broadcast address and the local address */ ipoib_mcast_dev_down(dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3aab4d8..36ce298 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -598,7 +598,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) return 0; } -int ipoib_mcast_stop_thread(struct net_device *dev) +int ipoib_mcast_stop_thread(struct net_device *dev, int flush) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_mcast *mcast; @@ -610,7 +610,8 @@ int ipoib_mcast_stop_thread(struct net_device *dev) cancel_delayed_work(&priv->mcast_task); up(&mcast_mutex); - flush_workqueue(ipoib_workqueue); + if (flush) + flush_workqueue(ipoib_workqueue); if (priv->broadcast && priv->broadcast->query) { ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); @@ -832,7 +833,7 @@ void ipoib_mcast_restart_task(void *dev_ptr) ipoib_dbg_mcast(priv, "restarting multicast task\n"); - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 0); spin_lock_irqsave(&priv->lock, flags); -- cgit v0.10.2 From 71eea47d853bb0ce0c6befe11b3e08111263170f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 20 Sep 2005 10:54:48 -0700 Subject: [PATCH] IB/mthca: Fix device removal memory leak Clean up QP table array on device removal. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index eaa5218..5fa0066 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2123,5 +2123,6 @@ void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) for (i = 0; i < 2; ++i) mthca_CONF_SPECIAL_QP(dev, i, 0, &status); + mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps); mthca_alloc_cleanup(&dev->qp_table.alloc); } -- cgit v0.10.2 From 729b4f7de68191478b20fab19a6d0c6b8c4380c9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Sep 2005 12:18:38 -0700 Subject: [SPARC64]: Verify vmalloc TLB misses more strictly. Arrange the modules, OBP, and vmalloc areas such that a range verification can be done quite minimally. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 3e0badb..b483495 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -42,19 +42,15 @@ * executing (see inherit_locked_prom_mappings() rant). */ sparc64_vpte_nucleus: - /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ - mov 0xf, %g5 - sllx %g5, 28, %g5 - - /* Is addr >= LOW_OBP_ADDRESS? */ + /* Note that kvmap below has verified that the address is + * in the range MODULES_VADDR --> VMALLOC_END already. So + * here we need only check if it is an OBP address or not. + */ + sethi %hi(LOW_OBP_ADDRESS), %g5 cmp %g4, %g5 blu,pn %xcc, sparc64_vpte_patchme1 mov 0x1, %g5 - - /* Load 0x100000000, which is HI_OBP_ADDRESS. */ sllx %g5, 32, %g5 - - /* Is addr < HI_OBP_ADDRESS? */ cmp %g4, %g5 blu,pn %xcc, obp_iaddr_patch nop @@ -156,26 +152,29 @@ obp_daddr_patch: * rather, use information saved during inherit_prom_mappings() using 8k * pagesize. */ + .align 32 kvmap: - /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ - mov 0xf, %g5 - sllx %g5, 28, %g5 + sethi %hi(MODULES_VADDR), %g5 + cmp %g4, %g5 + blu,pn %xcc, longpath + mov (VMALLOC_END >> 24), %g5 + sllx %g5, 24, %g5 + cmp %g4, %g5 + bgeu,pn %xcc, longpath + nop - /* Is addr >= LOW_OBP_ADDRESS? */ +kvmap_check_obp: + sethi %hi(LOW_OBP_ADDRESS), %g5 cmp %g4, %g5 - blu,pn %xcc, vmalloc_addr + blu,pn %xcc, kvmap_vmalloc_addr mov 0x1, %g5 - - /* Load 0x100000000, which is HI_OBP_ADDRESS. */ sllx %g5, 32, %g5 - - /* Is addr < HI_OBP_ADDRESS? */ cmp %g4, %g5 blu,pn %xcc, obp_daddr_patch nop -vmalloc_addr: - /* If we get here, a vmalloc addr accessed, load kernel VPTE. */ +kvmap_vmalloc_addr: + /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ ldxa [%g3 + %g6] ASI_N, %g5 brgez,pn %g5, longpath nop diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index a2b4f5e..a297f61 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -24,21 +24,23 @@ #include #include -/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 16MB). - * The page copy blockops use 0x1000000 to 0x18000000 (16MB --> 24MB). +/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB). + * The page copy blockops can use 0x2000000 to 0x10000000. * The PROM resides in an area spanning 0xf0000000 to 0x100000000. - * The vmalloc area spans 0x140000000 to 0x200000000. + * The vmalloc area spans 0x100000000 to 0x200000000. + * Since modules need to be in the lowest 32-bits of the address space, + * we place them right before the OBP area from 0x10000000 to 0xf0000000. * There is a single static kernel PMD which maps from 0x0 to address * 0x400000000. */ -#define TLBTEMP_BASE _AC(0x0000000001000000,UL) -#define MODULES_VADDR _AC(0x0000000002000000,UL) -#define MODULES_LEN _AC(0x000000007e000000,UL) -#define MODULES_END _AC(0x0000000080000000,UL) -#define VMALLOC_START _AC(0x0000000140000000,UL) -#define VMALLOC_END _AC(0x0000000200000000,UL) +#define TLBTEMP_BASE _AC(0x0000000002000000,UL) +#define MODULES_VADDR _AC(0x0000000010000000,UL) +#define MODULES_LEN _AC(0x00000000e0000000,UL) +#define MODULES_END _AC(0x00000000f0000000,UL) #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) +#define VMALLOC_START _AC(0x0000000100000000,UL) +#define VMALLOC_END _AC(0x0000000200000000,UL) /* XXX All of this needs to be rethought so we can take advantage * XXX cheetah's full 64-bit virtual address space, ie. no more hole -- cgit v0.10.2 From 438282d85de2c8f8c5183fdf55140e51a0b18670 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 20 Sep 2005 14:58:11 -0500 Subject: JFS: don't dereference tlck->ip from txUpdateMap The inode pointer may no longer be valid Signed-off-by: Dave Kleikamp diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 8132fce..9b71ed2 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -725,6 +725,9 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, else tlck->flag = tlckINODELOCK; + if (S_ISDIR(ip->i_mode)) + tlck->flag |= tlckDIRECTORY; + tlck->type = 0; /* bind the tlock and the page */ @@ -1009,6 +1012,8 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type) /* bind the tlock and the object */ tlck->flag = tlckINODELOCK; + if (S_ISDIR(ip->i_mode)) + tlck->flag |= tlckDIRECTORY; tlck->ip = ip; tlck->mp = NULL; @@ -1077,6 +1082,8 @@ struct linelock *txLinelock(struct linelock * tlock) linelock->flag = tlckLINELOCK; linelock->maxcnt = TLOCKLONG; linelock->index = 0; + if (tlck->flag & tlckDIRECTORY) + linelock->flag |= tlckDIRECTORY; /* append linelock after tlock */ linelock->next = tlock->next; @@ -2358,7 +2365,7 @@ static void txUpdateMap(struct tblock * tblk) */ else { /* (maplock->flag & mlckFREE) */ - if (S_ISDIR(tlck->ip->i_mode)) + if (tlck->flag & tlckDIRECTORY) txFreeMap(ipimap, maplock, tblk, COMMIT_PWMAP); else diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h index 59ad0f6..0e4dc45 100644 --- a/fs/jfs/jfs_txnmgr.h +++ b/fs/jfs/jfs_txnmgr.h @@ -122,6 +122,7 @@ extern struct tlock *TxLock; /* transaction lock table */ #define tlckLOG 0x0800 /* updateMap state */ #define tlckUPDATEMAP 0x0080 +#define tlckDIRECTORY 0x0040 /* freeLock state */ #define tlckFREELOCK 0x0008 #define tlckWRITEPAGE 0x0004 -- cgit v0.10.2 From a9f7baf4d695dbe3028d40ca374c1d11499eaee6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 20 Sep 2005 21:01:13 +0100 Subject: [ARM] Fix pcf8583 to build Seems that the Acorn RTC driver missed an update. Fix it. Signed-off-by: Russell King diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c index 141b4c2..2b850e5 100644 --- a/drivers/acorn/char/pcf8583.c +++ b/drivers/acorn/char/pcf8583.c @@ -23,12 +23,13 @@ static struct i2c_driver pcf8583_driver; static unsigned short ignore[] = { I2C_CLIENT_END }; static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; +static unsigned short *forces[] = { NULL }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_addr, .probe = ignore, .ignore = ignore, - .force = ignore, + .forces = forces, }; #define DAT(x) ((unsigned int)(x->dev.driver_data)) -- cgit v0.10.2 From 7a482425f45e695a2e2821b32a887865f016fbf9 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Wed, 21 Sep 2005 07:30:21 +0800 Subject: [PATCH] nvidiafb: Fix absence of cursor in nvidiafb A recent change in nvidiafb caused nvidiafb_cursor to always return -ENXIO instead of using the soft_cursor. This will happen if the parameter "hwcur" is not set, which happens to be the default. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 31ee13e..773ae11 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -650,6 +650,7 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_SOFT_CURSOR help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 3620de0..a7f020a 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -893,7 +893,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor) int i, set = cursor->set; u16 fg, bg; - if (!hwcur || cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) + if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) return -ENXIO; NVShowHideCursor(par, 0); @@ -1356,6 +1356,9 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.size = 8 * 1024; info->pixmap.flags = FB_PIXMAP_SYSTEM; + if (!hwcur) + info->fbops->fb_cursor = soft_cursor; + info->var.accel_flags = (!noaccel); switch (par->Architecture) { -- cgit v0.10.2 From 6d67e34de5a378de2f461137944c5d931283d557 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Wed, 21 Sep 2005 07:32:49 +0800 Subject: [PATCH] fbdev: Fix reversed back and front porches In fbdev perspective, the frontporch is the lower/right margin and the backporch is the upper/left margin. Correct. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index cfa61b5..0b6af00 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c @@ -272,11 +272,11 @@ static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt, { mode->refresh = cvt->f_refresh; mode->pixclock = KHZ2PICOS(cvt->pixclock/1000); - mode->left_margin = cvt->h_front_porch; - mode->right_margin = cvt->h_back_porch; + mode->left_margin = cvt->h_back_porch; + mode->right_margin = cvt->h_front_porch; mode->hsync_len = cvt->hsync; - mode->upper_margin = cvt->v_front_porch; - mode->lower_margin = cvt->v_back_porch; + mode->upper_margin = cvt->v_back_porch; + mode->lower_margin = cvt->v_front_porch; mode->vsync_len = cvt->vsync; mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); -- cgit v0.10.2 From 0fb375fb9b93b7d822debc6a734052337ccfdb1f Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 21 Sep 2005 00:11:37 -0700 Subject: [AF_PACKET]: Allow for > 8 byte hardware addresses. The convention is that longer addresses will simply extend the hardeware address byte arrays at the end of sockaddr_ll and packet_mreq. In making this change a small information leak was also closed. The code only initializes the hardware address bytes that are used, but all of struct sockaddr_ll was copied to userspace. Now we just copy sockaddr_ll to the last byte of the hardware address used. For error checking larger structures than our internal maximums continue to be allowed but an error is signaled if we can not fit the hardware address into our internal structure. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8690f17..ee865d8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -36,6 +36,11 @@ * Michal Ostrowski : Module initialization cleanup. * Ulises Alonso : Frame number limit removal and * packet_set_ring memory leak. + * Eric Biederman : Allow for > 8 byte hardware addresses. + * The convention is that longer addresses + * will simply extend the hardware address + * byte arrays at the end of sockaddr_ll + * and packet_mreq. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -161,7 +166,17 @@ struct packet_mclist int count; unsigned short type; unsigned short alen; - unsigned char addr[8]; + unsigned char addr[MAX_ADDR_LEN]; +}; +/* identical to struct packet_mreq except it has + * a longer address field. + */ +struct packet_mreq_max +{ + int mr_ifindex; + unsigned short mr_type; + unsigned short mr_alen; + unsigned char mr_address[MAX_ADDR_LEN]; }; #endif #ifdef CONFIG_PACKET_MMAP @@ -716,6 +731,8 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, err = -EINVAL; if (msg->msg_namelen < sizeof(struct sockaddr_ll)) goto out; + if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) + goto out; ifindex = saddr->sll_ifindex; proto = saddr->sll_protocol; addr = saddr->sll_addr; @@ -744,6 +761,12 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, if (dev->hard_header) { int res; err = -EINVAL; + if (saddr) { + if (saddr->sll_halen != dev->addr_len) + goto out_free; + if (saddr->sll_hatype != dev->type) + goto out_free; + } res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); if (sock->type != SOCK_DGRAM) { skb->tail = skb->data; @@ -1045,6 +1068,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; struct sk_buff *skb; int copied, err; + struct sockaddr_ll *sll; err = -EINVAL; if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) @@ -1057,16 +1081,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, #endif /* - * If the address length field is there to be filled in, we fill - * it in now. - */ - - if (sock->type == SOCK_PACKET) - msg->msg_namelen = sizeof(struct sockaddr_pkt); - else - msg->msg_namelen = sizeof(struct sockaddr_ll); - - /* * Call the generic datagram receiver. This handles all sorts * of horrible races and re-entrancy so we can forget about it * in the protocol layers. @@ -1087,6 +1101,17 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, goto out; /* + * If the address length field is there to be filled in, we fill + * it in now. + */ + + sll = (struct sockaddr_ll*)skb->cb; + if (sock->type == SOCK_PACKET) + msg->msg_namelen = sizeof(struct sockaddr_pkt); + else + msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); + + /* * You lose any data beyond the buffer you gave. If it worries a * user program they can ask the device for its MTU anyway. */ @@ -1166,7 +1191,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ sll->sll_halen = 0; } - *uaddr_len = sizeof(*sll); + *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; return 0; } @@ -1199,7 +1224,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i } } -static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) +static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq) { struct packet_sock *po = pkt_sk(sk); struct packet_mclist *ml, *i; @@ -1249,7 +1274,7 @@ done: return err; } -static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) +static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq) { struct packet_mclist *ml, **mlp; @@ -1315,11 +1340,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv case PACKET_ADD_MEMBERSHIP: case PACKET_DROP_MEMBERSHIP: { - struct packet_mreq mreq; - if (optlen sizeof(mreq)) + len = sizeof(mreq); + if (copy_from_user(&mreq,optval,len)) return -EFAULT; + if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address))) + return -EINVAL; if (optname == PACKET_ADD_MEMBERSHIP) ret = packet_mc_add(sk, &mreq); else -- cgit v0.10.2 From 78c6671a88313fd3c4364dc46e8c8186612616b8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 21 Sep 2005 00:15:39 -0700 Subject: [FIB_TRIE]: message cleanup Cleanup the printk's in fib_trie: * Convert a couple of places in the dump code to BUG_ON * Put log level's on each message The version message really needed the message since it leaks out on the pretty Fedora bootup. Signed-off-by: Stephen Hemminger Acked-by: Robert Olsson , Signed-off-by: David S. Miller diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 90ae708..50c0519 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1086,7 +1086,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) } if (tp && tp->pos + tp->bits > 32) - printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", + printk(KERN_WARNING "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", tp, tp->pos, tp->bits, key, plen); /* Rebalance the trie */ @@ -1832,16 +1832,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi i++; continue; } - if (fa->fa_info->fib_nh == NULL) { - printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); - i++; - continue; - } - if (fa->fa_info == NULL) { - printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); - i++; - continue; - } + BUG_ON(!fa->fa_info); if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, @@ -1964,7 +1955,7 @@ struct fib_table * __init fib_hash_init(int id) trie_main = t; if (id == RT_TABLE_LOCAL) - printk("IPv4 FIB: Using LC-trie version %s\n", VERSION); + printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION); return tb; } -- cgit v0.10.2 From 7957aed72b104f7528da484f292442c6f3a131a1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 21 Sep 2005 00:19:46 -0700 Subject: [TCP]: Set default congestion control correctly for incoming connections. Patch from Joel Sing to fix the default congestion control algorithm for incoming connections. If a new congestion control handler is added (via module), it should become the default for new connections. Instead, the incoming connections use reno. The cause is incorrect initialisation causes the tcp_init_congestion_control() function to return after the initial if test fails. Signed-off-by: Stephen Hemminger Acked-by: Ian McDonald Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index a88db28..b1a63b2 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -384,7 +384,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->frto_counter = 0; newtp->frto_highmark = 0; - newicsk->icsk_ca_ops = &tcp_reno; + newicsk->icsk_ca_ops = &tcp_init_congestion_ops; tcp_set_ca_state(newsk, TCP_CA_Open); tcp_init_xmit_timers(newsk); -- cgit v0.10.2 From 1a3e64aa480101d11d8cac94ca57fd8bbe2536b7 Mon Sep 17 00:00:00 2001 From: Tom 'spot' Callaway Date: Wed, 21 Sep 2005 00:29:16 -0700 Subject: [ATYFB]: Fix build with CONFIG_FB_ATY_GENERIC_LCD disabled. Signed-off-by: Tom 'spot' Callaway Signed-off-by: David S. Miller diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c index 92643af..0bea0d8 100644 --- a/drivers/video/aty/xlinit.c +++ b/drivers/video/aty/xlinit.c @@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info) const struct xl_card_cfg_t * card = &card_cfg[xl_card]; struct atyfb_par *par = (struct atyfb_par *) info->par; union aty_pll pll; - int i, err; + int err; u32 temp; aty_st_8(CONFIG_STAT0, 0x85, par); @@ -252,9 +252,12 @@ int atyfb_xl_init(struct fb_info *info) aty_st_le32(0xEC, 0x00000000, par); aty_st_le32(0xFC, 0x00000000, par); +#if defined (CONFIG_FB_ATY_GENERIC_LCD) + int i; for (i=0; i Date: Wed, 21 Sep 2005 00:41:22 -0700 Subject: [SPARC] cs4231: Fix SBUS support in this driver. From: Christopher Zimmermann This patch enables SBus support for the cs4231 sound driver. It is tested on an Ultra2. Capture and playback both work. I experienced lags and crashes using certain threaded players like ogg123 and mp3blaster, while the former is lagging far more. This behavior may be specific to SMP systems. It is reproducable using the dummy sound card driver. Sox works flawlessly. Setting up the calculation of ptr in snd_cs4231_playback_pointer was a bit strange. I got it to work by not incrementing the [pc]_periods_sent counter when starting DMA the first time in cs4231_dma_trigger. Therefore this dummy thing. [ I did some minor cleanups -DaveM ] Signed-off-by: David S. Miller diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 2fb27c4..f4361c5 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -173,7 +173,7 @@ static cs4231_t *cs4231_list; #define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ -/* definitions for codec irq status */ +/* definitions for codec irq status - CS4231_IRQ_STATUS */ #define CS4231_PLAYBACK_IRQ 0x10 #define CS4231_RECORD_IRQ 0x20 @@ -402,7 +402,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, udelay(100); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif if (chip->calibrate_mute) { chip->image[reg] &= mask; @@ -425,6 +425,10 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--) udelay(100); +#ifdef CONFIG_SND_DEBUG + if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) + snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); +#endif __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, value, CS4231P(chip, REG)); mb(); @@ -440,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu udelay(100); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, value, CS4231P(chip, REG)); chip->image[reg] = value; mb(); -#if 0 - printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); -#endif } static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) @@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) udelay(100); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); + snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg); #endif __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); mb(); ret = __cs4231_readb(chip, CS4231P(chip, REG)); -#if 0 - printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret); -#endif return ret; } -#if 0 - -static void snd_cs4231_debug(cs4231_t *chip) -{ - printk("CS4231 REGS: INDEX = 0x%02x ", - __cs4231_readb(chip, CS4231P(chip, REGSEL))); - printk(" STATUS = 0x%02x\n", - __cs4231_readb(chip, CS4231P(chip, STATUS))); - printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00)); - printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10)); - printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01)); - printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11)); - printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02)); - printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12)); - printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03)); - printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13)); - printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04)); - printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14)); - printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05)); - printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15)); - printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06)); - printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16)); - printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07)); - printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17)); - printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08)); - printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18)); - printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09)); - printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19)); - printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a)); - printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a)); - printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b)); - printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b)); - printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c)); - printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c)); - printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d)); - printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d)); - printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e)); - printk(" 0x1e: rec upr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e)); - printk(" 0x0f: ply lwr count = 0x%02x ", snd_cs4231_in(chip, 0x0f)); - printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f)); -} - -#endif - /* * CS4231 detection / MCE routines */ @@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip) /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ for (timeout = 5; timeout > 0; timeout--) __cs4231_readb(chip, CS4231P(chip, REGSEL)); + /* end of cleanup sequence */ - for (timeout = 250; + for (timeout = 500; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--) - udelay(100); + udelay(1000); } static void snd_cs4231_mce_up(cs4231_t *chip) @@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip) udelay(100); #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printk("mce_up - auto calibration time out (0)\n"); + snd_printdd("mce_up - auto calibration time out (0)\n"); #endif chip->mce_bit |= CS4231_MCE; timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); if (timeout == 0x80) - snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port); + snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port); if (!(timeout & CS4231_MCE)) __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); spin_unlock_irqrestore(&chip->lock, flags); @@ -563,18 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip) spin_lock_irqsave(&chip->lock, flags); snd_cs4231_busy_wait(chip); -#if 0 - printk("(1) timeout = %i\n", timeout); -#endif #ifdef CONFIG_SND_DEBUG if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); + snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); #endif chip->mce_bit &= ~CS4231_MCE; timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); if (timeout == 0x80) - snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port); + snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port); if ((timeout & CS4231_MCE) == 0) { spin_unlock_irqrestore(&chip->lock, flags); return; @@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) spin_unlock_irqrestore(&chip->lock, flags); return; } -#if 0 - printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); -#endif + /* in 10ms increments, check condition, up to 250ms */ timeout = 25; while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { @@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) msleep(10); spin_lock_irqsave(&chip->lock, flags); } -#if 0 - printk("(3) jiffies = %li\n", jiffies); -#endif + /* in 10ms increments, check condition, up to 100ms */ timeout = 10; while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { @@ -619,54 +567,58 @@ static void snd_cs4231_mce_down(cs4231_t *chip) spin_lock_irqsave(&chip->lock, flags); } spin_unlock_irqrestore(&chip->lock, flags); -#if 0 - printk("(4) jiffies = %li\n", jiffies); - snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL))); -#endif } -#if 0 /* Unused for now... */ -static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) -{ - switch (format & 0xe0) { - case CS4231_LINEAR_16: - case CS4231_LINEAR_16_BIG: - size >>= 1; - break; - case CS4231_ADPCM_16: - return size >> 2; - } - if (format & CS4231_STEREO) - size >>= 1; - return size; -} -#endif - #ifdef EBUS_SUPPORT static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) { snd_pcm_runtime_t *runtime = substream->runtime; while (1) { - unsigned int dma_size = snd_pcm_lib_period_bytes(substream); - unsigned int offset = dma_size * (*periods_sent); + unsigned int period_size = snd_pcm_lib_period_bytes(substream); + unsigned int offset = period_size * (*periods_sent); - if (dma_size >= (1 << 24)) + if (period_size >= (1 << 24)) BUG(); - if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size)) + if (ebus_dma_request(p, runtime->dma_addr + offset, period_size)) return; -#if 0 - printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n", - (*periods_sent), dma_size, offset); -#endif (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; } } #endif -static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) +#ifdef SBUS_SUPPORT +static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent) +{ + cs4231_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; + + unsigned int period_size = snd_pcm_lib_period_bytes(substream); + unsigned int offset = period_size * (*periods_sent % runtime->periods); + + if (runtime->period_size > 0xffff + 1) + BUG(); + + switch (substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA); + sbus_writel(period_size, chip->port + APCPNC); + break; + case SNDRV_PCM_STREAM_CAPTURE: + sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA); + sbus_writel(period_size, chip->port + APCCNC); + break; + } + + (*periods_sent) = (*periods_sent + 1) % runtime->periods; +} +#endif + +static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) { + cs4231_t *chip = snd_pcm_substream_chip(substream); + #ifdef EBUS_SUPPORT if (chip->flags & CS4231_FLAG_EBUS) { if (what & CS4231_PLAYBACK_ENABLE) { @@ -694,6 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) } else { #endif #ifdef SBUS_SUPPORT + u32 csr = sbus_readl(chip->port + APCCSR); + /* I don't know why, but on sbus the period counter must + * only start counting after the first period is sent. + * Therefore this dummy thing. + */ + unsigned int dummy = 0; + + switch (what) { + case CS4231_PLAYBACK_ENABLE: + if (on) { + csr &= ~APC_XINT_PLAY; + sbus_writel(csr, chip->port + APCCSR); + + csr &= ~APC_PPAUSE; + sbus_writel(csr, chip->port + APCCSR); + + snd_cs4231_sbus_advance_dma(substream, &dummy); + + csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | + APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | + APC_XINT_PENA | APC_PDMA_READY; + sbus_writel(csr, chip->port + APCCSR); + } else { + csr |= APC_PPAUSE; + sbus_writel(csr, chip->port + APCCSR); + + csr &= ~APC_PDMA_READY; + sbus_writel(csr, chip->port + APCCSR); + } + break; + case CS4231_RECORD_ENABLE: + if (on) { + csr &= ~APC_XINT_CAPT; + sbus_writel(csr, chip->port + APCCSR); + + csr &= ~APC_CPAUSE; + sbus_writel(csr, chip->port + APCCSR); + + snd_cs4231_sbus_advance_dma(substream, &dummy); + + csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | + APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | + APC_CDMA_READY; + + sbus_writel(csr, chip->port + APCCSR); + } else { + csr |= APC_CPAUSE; + sbus_writel(csr, chip->port + APCCSR); + + csr &= ~APC_CDMA_READY; + sbus_writel(csr, chip->port + APCCSR); + } + break; + } #endif #ifdef EBUS_SUPPORT } @@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) } } -#if 0 - printk("TRIGGER: what[%x] on(%d)\n", - what, (cmd == SNDRV_PCM_TRIGGER_START)); -#endif - spin_lock_irqsave(&chip->lock, flags); if (cmd == SNDRV_PCM_TRIGGER_START) { - cs4231_dma_trigger(chip, what, 1); + cs4231_dma_trigger(substream, what, 1); chip->image[CS4231_IFACE_CTRL] |= what; - if (what & CS4231_PLAYBACK_ENABLE) { - snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff); - snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff); - } - if (what & CS4231_RECORD_ENABLE) { - snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff); - snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff); - } } else { - cs4231_dma_trigger(chip, what, 0); + cs4231_dma_trigger(substream, what, 0); chip->image[CS4231_IFACE_CTRL] &= ~what; } snd_cs4231_out(chip, CS4231_IFACE_CTRL, @@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) result = -EINVAL; break; } -#if 0 - snd_cs4231_debug(chip); -#endif + return result; } @@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann } if (channels > 1) rformat |= CS4231_STEREO; -#if 0 - snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); -#endif return rformat; } @@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (1)\n"); + snd_printdd("init: (1)\n"); #endif snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); @@ -957,7 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (2)\n"); + snd_printdd("init: (2)\n"); #endif snd_cs4231_mce_up(chip); @@ -967,7 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); + snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->lock, flags); @@ -981,7 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (4)\n"); + snd_printdd("init: (4)\n"); #endif snd_cs4231_mce_up(chip); @@ -991,7 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip) snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (5)\n"); + snd_printdd("init: (5)\n"); #endif } @@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode) CS4231_RECORD_IRQ | CS4231_TIMER_IRQ); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); + spin_unlock_irqrestore(&chip->lock, flags); chip->mode = mode; @@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream) static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; unsigned long flags; spin_lock_irqsave(&chip->lock, flags); + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); + + if (runtime->period_size > 0xffff + 1) + BUG(); + + snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff); + snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); + chip->p_periods_sent = 0; + spin_unlock_irqrestore(&chip->lock, flags); return 0; @@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream) static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) { cs4231_t *chip = snd_pcm_substream_chip(substream); + snd_pcm_runtime_t *runtime = substream->runtime; unsigned long flags; spin_lock_irqsave(&chip->lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); + snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff); + snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); + spin_unlock_irqrestore(&chip->lock, flags); return 0; @@ -1196,53 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip) chip->capture_substream->runtime->overrange++; } -static void snd_cs4231_generic_interrupt(cs4231_t *chip) +static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip) { unsigned long flags; unsigned char status; + /*This is IRQ is not raised by the cs4231*/ + if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) + return IRQ_NONE; + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); - if (!status) - return; if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); } - if (status & CS4231_PLAYBACK_IRQ) - snd_pcm_period_elapsed(chip->playback_substream); - if (status & CS4231_RECORD_IRQ) { + + if (status & CS4231_RECORD_IRQ) snd_cs4231_overrange(chip); - snd_pcm_period_elapsed(chip->capture_substream); - } /* ACK the CS4231 interrupt. */ spin_lock_irqsave(&chip->lock, flags); snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); spin_unlock_irqrestore(&chip->lock, flags); + + return 0; } #ifdef SBUS_SUPPORT static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) { cs4231_t *chip = dev_id; - u32 csr; - - csr = sbus_readl(chip->port + APCCSR); - if (!(csr & (APC_INT_PENDING | - APC_PLAY_INT | - APC_CAPT_INT | - APC_GENL_INT | - APC_XINT_PEMP | - APC_XINT_CEMP))) - return IRQ_NONE; /* ACK the APC interrupt. */ + u32 csr = sbus_readl(chip->port + APCCSR); + sbus_writel(csr, chip->port + APCCSR); - snd_cs4231_generic_interrupt(chip); + if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) && + (csr & APC_PLAY_INT) && + (csr & APC_XINT_PNVA) && + !(csr & APC_XINT_EMPT)) { + snd_cs4231_sbus_advance_dma(chip->playback_substream, + &chip->p_periods_sent); + snd_pcm_period_elapsed(chip->playback_substream); + } - return IRQ_HANDLED; + if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && + (csr & APC_CAPT_INT) && + (csr & APC_XINT_CNVA)) { + snd_cs4231_sbus_advance_dma(chip->capture_substream, + &chip->c_periods_sent); + snd_pcm_period_elapsed(chip->capture_substream); + } + + return snd_cs4231_generic_interrupt(chip); } #endif @@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr #ifdef EBUS_SUPPORT } #endif - ptr += (period_bytes - residue); + ptr += period_bytes - residue; + return bytes_to_frames(substream->runtime, ptr); } @@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr #ifdef EBUS_SUPPORT } #endif - ptr += (period_bytes - residue); + ptr += period_bytes - residue; return bytes_to_frames(substream->runtime, ptr); } @@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip) int i, id, vers; unsigned char *ptr; -#if 0 - snd_cs4231_debug(chip); -#endif id = vers = 0; for (i = 0; i < 50; i++) { mb(); @@ -1985,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, chip->port = sbus_ioremap(&sdev->resource[0], 0, chip->regs_size, "cs4231"); if (!chip->port) { - snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); + snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, SA_SHIRQ, "cs4231", chip)) { - snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n", + snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", dev, __irq_itoa(sdev->irqs[0])); snd_cs4231_sbus_free(chip); @@ -2113,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { snd_cs4231_ebus_free(chip); - snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); + snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; } if (ebus_dma_register(&chip->eb2c)) { snd_cs4231_ebus_free(chip); - snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->eb2c, 1)) { snd_cs4231_ebus_free(chip); - snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); + snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); return -EBUSY; } if (ebus_dma_register(&chip->eb2p)) { snd_cs4231_ebus_free(chip); - snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->eb2p, 1)) { snd_cs4231_ebus_free(chip); - snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); + snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); return -EBUSY; } -- cgit v0.10.2 From d79e743e9fcf03f521300a970eb1ab69641910ba Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 21 Sep 2005 14:14:22 +1000 Subject: [PATCH] ppc64: Fix PCI flags when using OF device tree My code to set up the PCI tree from the Open Firmware device tree was setting IORESOURCE_* flags on the resources for the devices, but not the PCI_BASE_ADDRESS_* flags. This meant that some drivers misbehaved, and /proc/pci showed the wrong types for the resources. This fixes it. Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 861138a..ff4be1d 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -246,11 +246,14 @@ static unsigned int pci_parse_of_flags(u32 addr0) unsigned int flags = 0; if (addr0 & 0x02000000) { - flags |= IORESOURCE_MEM; + flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; + flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; + flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; if (addr0 & 0x40000000) - flags |= IORESOURCE_PREFETCH; + flags |= IORESOURCE_PREFETCH + | PCI_BASE_ADDRESS_MEM_PREFETCH; } else if (addr0 & 0x01000000) - flags |= IORESOURCE_IO; + flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; return flags; } -- cgit v0.10.2 From 66dcca062847bcd261ebb3ac96d51101f31a8630 Mon Sep 17 00:00:00 2001 From: Sripathi Kodi Date: Mon, 19 Sep 2005 18:26:12 -0500 Subject: [PATCH] Fix invisible threads problem When the main thread of a thread group has done pthread_exit() and died, the other threads are still happily running, but will not be visible under /proc because their leader is no longer accessible. This fixes the access control so that we can see the sub-threads again. Signed-off-by: Sripathi Kodi Acked-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 23db452..fb34f88 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -340,6 +340,52 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf return result; } + +/* Same as proc_root_link, but this addionally tries to get fs from other + * threads in the group */ +static int proc_task_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +{ + struct fs_struct *fs; + int result = -ENOENT; + struct task_struct *leader = proc_task(inode); + + task_lock(leader); + fs = leader->fs; + if (fs) { + atomic_inc(&fs->count); + task_unlock(leader); + } else { + /* Try to get fs from other threads */ + task_unlock(leader); + struct task_struct *task = leader; + read_lock(&tasklist_lock); + if (pid_alive(task)) { + while ((task = next_thread(task)) != leader) { + task_lock(task); + fs = task->fs; + if (fs) { + atomic_inc(&fs->count); + task_unlock(task); + break; + } + task_unlock(task); + } + } + read_unlock(&tasklist_lock); + } + + if (fs) { + read_lock(&fs->lock); + *mnt = mntget(fs->rootmnt); + *dentry = dget(fs->root); + read_unlock(&fs->lock); + result = 0; + put_fs_struct(fs); + } + return result; +} + + #define MAY_PTRACE(task) \ (task == current || \ (task->parent == current && \ @@ -471,14 +517,14 @@ static int proc_oom_score(struct task_struct *task, char *buffer) /* permission checks */ -static int proc_check_root(struct inode *inode) +/* If the process being read is separated by chroot from the reading process, + * don't let the reader access the threads. + */ +static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt) { - struct dentry *de, *base, *root; - struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; + struct dentry *de, *base; + struct vfsmount *our_vfsmnt, *mnt; int res = 0; - - if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ - return -ENOENT; read_lock(¤t->fs->lock); our_vfsmnt = mntget(current->fs->rootmnt); base = dget(current->fs->root); @@ -511,6 +557,16 @@ out: goto exit; } +static int proc_check_root(struct inode *inode) +{ + struct dentry *root; + struct vfsmount *vfsmnt; + + if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ + return -ENOENT; + return proc_check_chroot(root, vfsmnt); +} + static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) { if (generic_permission(inode, mask, NULL) != 0) @@ -518,6 +574,20 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) return proc_check_root(inode); } +static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + struct dentry *root; + struct vfsmount *vfsmnt; + + if (generic_permission(inode, mask, NULL) != 0) + return -EACCES; + + if (proc_task_root_link(inode, &root, &vfsmnt)) + return -ENOENT; + + return proc_check_chroot(root, vfsmnt); +} + extern struct seq_operations proc_pid_maps_op; static int maps_open(struct inode *inode, struct file *file) { @@ -1419,7 +1489,7 @@ static struct inode_operations proc_fd_inode_operations = { static struct inode_operations proc_task_inode_operations = { .lookup = proc_task_lookup, - .permission = proc_permission, + .permission = proc_task_permission, }; #ifdef CONFIG_SECURITY -- cgit v0.10.2 From 31f6d9d628739c097964b8dbae939ea997da94a3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 21 Sep 2005 09:55:30 -0700 Subject: [PATCH] Add printk_clock() ia64's sched_clock() accesses per-cpu data which isn't set up at boot time. Hence ia64 cannot use printk timestamping, because printk() will crash in sched_clock(). So make printk() use printk_clock(), defaulting to sched_clock(), overrideable by the architecture via attribute(weak). Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/printk.c b/kernel/printk.c index a967605..4b8f0f9 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -488,6 +488,11 @@ static int __init printk_time_setup(char *str) __setup("time", printk_time_setup); +__attribute__((weak)) unsigned long long printk_clock(void) +{ + return sched_clock(); +} + /* * This is printk. It can be called from any context. We want it to work. * @@ -565,7 +570,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) loglev_char = default_message_loglevel + '0'; } - t = sched_clock(); + t = printk_clock(); nanosec_rem = do_div(t, 1000000000); tlen = sprintf(tbuf, "<%c>[%5lu.%06lu] ", -- cgit v0.10.2 From 3c2822ccb1f8cc96fc006aa82e68e1944290014a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 21 Sep 2005 09:55:31 -0700 Subject: [PATCH] PPC64: Fix boot for some pre-POWER4 systems Some RS64 systems (such as F80) have non-python host bridges with EADS. However, they have two EADS with 4 buses each under them, so the old logic that assumed no more than 7 busses per PHB failed miserably. Big thanks to Olaf Hering for helping me test this, he's got one of the few machines that broke from the previous logic. Also, to be a bit smarter at detecting the need for a PHB-level IOMMU table by checking for the presence of an ISA bus. Only PHBs with ISA bridges should need the PHB-level table. Signed-off-by: Olof Johansson Cc: Anton Blanchard Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index f0fd7fb..8c6313e 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb, tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; /* Test if we are going over 2GB of DMA space */ - if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31)) + if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { + udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + } phb->dma_window_base_cur += phb->dma_window_size; @@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, static void iommu_bus_setup_pSeries(struct pci_bus *bus) { - struct device_node *dn, *pdn; - struct pci_dn *pci; + struct device_node *dn; struct iommu_table *tbl; + struct device_node *isa_dn, *isa_dn_orig; + struct device_node *tmp; + struct pci_dn *pci; + int children; DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); - /* For each (root) bus, we carve up the available DMA space in 256MB - * pieces. Since each piece is used by one (sub) bus/device, that would - * give a maximum of 7 devices per PHB. In most cases, this is plenty. - * - * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS - * bridges below the PHB to allocate the sectioned tables to, so instead - * we allocate a 1GB table at the PHB level. + dn = pci_bus_to_OF_node(bus); + pci = PCI_DN(dn); + + if (bus->self) { + /* This is not a root bus, any setup will be done for the + * device-side of the bridge in iommu_dev_setup_pSeries(). + */ + return; + } + + /* Check if the ISA bus on the system is under + * this PHB. */ + isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa"); - dn = pci_bus_to_OF_node(bus); - pci = dn->data; - - if (!bus->self) { - /* Root bus */ - if (is_python(dn)) { - unsigned int *iohole; - - DBG("Python root bus %s\n", bus->name); - - iohole = (unsigned int *)get_property(dn, "io-hole", 0); - - if (iohole) { - /* On first bus we need to leave room for the - * ISA address space. Just skip the first 256MB - * alltogether. This leaves 768MB for the window. - */ - DBG("PHB has io-hole, reserving 256MB\n"); - pci->phb->dma_window_size = 3 << 28; - pci->phb->dma_window_base_cur = 1 << 28; - } else { - /* 1GB window by default */ - pci->phb->dma_window_size = 1 << 30; - pci->phb->dma_window_base_cur = 0; - } - - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); - } else { - /* Do a 128MB table at root. This is used for the IDE - * controller on some SMP-mode POWER4 machines. It - * doesn't hurt to allocate it on other machines - * -- it'll just be unused since new tables are - * allocated on the EADS level. - * - * Allocate at offset 128MB to avoid having to deal - * with ISA holes; 128MB table for IDE is plenty. - */ - pci->phb->dma_window_size = 1 << 27; - pci->phb->dma_window_base_cur = 1 << 27; - - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); - - /* All child buses have 256MB tables */ - pci->phb->dma_window_size = 1 << 28; - } - } else { - pdn = pci_bus_to_OF_node(bus->parent); + while (isa_dn && isa_dn != dn) + isa_dn = isa_dn->parent; + + if (isa_dn_orig) + of_node_put(isa_dn_orig); - if (!bus->parent->self && !is_python(pdn)) { - struct iommu_table *tbl; - /* First child and not python means this is the EADS - * level. Allocate new table for this slot with 256MB - * window. - */ + /* Count number of direct PCI children of the PHB. + * All PCI device nodes have class-code property, so it's + * an easy way to find them. + */ + for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) + if (get_property(tmp, "class-code", NULL)) + children++; - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + DBG("Children: %d\n", children); - iommu_table_setparms(pci->phb, dn, tbl); + /* Calculate amount of DMA window per slot. Each window must be + * a power of two (due to pci_alloc_consistent requirements). + * + * Keep 256MB aside for PHBs with ISA. + */ - pci->iommu_table = iommu_init_table(tbl); - } else { - /* Lower than first child or under python, use parent table */ - pci->iommu_table = PCI_DN(pdn)->iommu_table; - } + if (!isa_dn) { + /* No ISA/IDE - just set window size and return */ + pci->phb->dma_window_size = 0x80000000ul; /* To be divided */ + + while (pci->phb->dma_window_size * children > 0x80000000ul) + pci->phb->dma_window_size >>= 1; + DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + pci->phb->dma_window_base_cur = 0; + + return; } + + /* If we have ISA, then we probably have an IDE + * controller too. Allocate a 128MB table but + * skip the first 128MB to avoid stepping on ISA + * space. + */ + pci->phb->dma_window_size = 0x8000000ul; + pci->phb->dma_window_base_cur = 0x8000000ul; + + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + + iommu_table_setparms(pci->phb, dn, tbl); + pci->iommu_table = iommu_init_table(tbl); + + /* Divide the rest (1.75GB) among the children */ + pci->phb->dma_window_size = 0x80000000ul; + while (pci->phb->dma_window_size * children > 0x70000000ul) + pci->phb->dma_window_size >>= 1; + + DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + } @@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) static void iommu_dev_setup_pSeries(struct pci_dev *dev) { struct device_node *dn, *mydn; + struct iommu_table *tbl; DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); - /* Now copy the iommu_table ptr from the bus device down to the - * pci device_node. This means get_iommu_table() won't need to search - * up the device tree to find it. - */ + mydn = dn = pci_device_to_OF_node(dev); + /* If we're the direct child of a root bus, then we need to allocate + * an iommu table ourselves. The bus setup code should have setup + * the window sizes already. + */ + if (!dev->bus->self) { + DBG(" --> first child, no bridge. Allocating iommu table.\n"); + tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); + PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); + + return; + } + + /* If this device is further down the bus tree, search upwards until + * an already allocated iommu table is found and use that. + */ + while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) dn = dn->parent; -- cgit v0.10.2 From d6dbf42ee36d4f9ffc2a93877c19937c81974124 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Wed, 21 Sep 2005 09:55:32 -0700 Subject: [PATCH] cciss: busy_initializing bug fix This patch fixes the problem Bjorn reported. The busy_initializing flag should have cleared before going into the for loop. Signed-off-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c56f995..486b6e1 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -483,9 +483,6 @@ static int cciss_open(struct inode *inode, struct file *filep) printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); #endif /* CCISS_DEBUG */ - if (host->busy_initializing) - return -EBUSY; - if (host->busy_initializing || drv->busy_configuring) return -EBUSY; /* @@ -2991,6 +2988,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); cciss_procinit(i); + hba[i]->busy_initializing = 0; for(j=0; j < NWD; j++) { /* mfm */ drive_info_struct *drv = &(hba[i]->drv[j]); @@ -3033,7 +3031,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, add_disk(disk); } - hba[i]->busy_initializing = 0; return(1); clean4: -- cgit v0.10.2 From 1bc2a3bb86688ffca691ba2ad30a2d5dcba774cf Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 21 Sep 2005 09:55:33 -0700 Subject: [PATCH] ppc64: Fix issue with non zero boot cpu The new version of the flattened device tree passes the boot cpuid in the header instead of via a linux,boot-cpu property. We need to update the in kernel OF parsing code to do this, otherwise machines with a non zero boot cpuid fail to come up. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 9979919..f252670 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c @@ -1711,6 +1711,7 @@ static void __init flatten_device_tree(void) unsigned long offset = reloc_offset(); unsigned long mem_start, mem_end, room; struct boot_param_header *hdr; + struct prom_t *_prom = PTRRELOC(&prom); char *namep; u64 *rsvmap; @@ -1765,6 +1766,7 @@ static void __init flatten_device_tree(void) RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); /* Finish header */ + hdr->boot_cpuid_phys = _prom->cpu; hdr->magic = OF_DT_HEADER; hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); @@ -1854,7 +1856,6 @@ static void __init prom_find_boot_cpu(void) cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); - prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0); prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); _prom->cpu = getprop_rval; -- cgit v0.10.2 From bbcc6bee9e5bf45ec35e87a4e0755dff09fe25d4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 21 Sep 2005 09:55:33 -0700 Subject: [PATCH] remove blkdev_scsi_issue_flush_fn again This function was removed a while ago, but crept in again via a recent scsi merge. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 483d71b..baedac5 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -2373,44 +2373,6 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) EXPORT_SYMBOL(blkdev_issue_flush); -/** - * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices - * @q: device queue - * @disk: gendisk - * @error_sector: error offset - * - * Description: - * Devices understanding the SCSI command set, can use this function as - * a helper for issuing a cache flush. Note: driver is required to store - * the error offset (in case of error flushing) in ->sector of struct - * request. - */ -int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, - sector_t *error_sector) -{ - struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT); - int ret; - - rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; - rq->sector = 0; - memset(rq->cmd, 0, sizeof(rq->cmd)); - rq->cmd[0] = 0x35; - rq->cmd_len = 12; - rq->data = NULL; - rq->data_len = 0; - rq->timeout = 60 * HZ; - - ret = blk_execute_rq(q, disk, rq, 0); - - if (ret && error_sector) - *error_sector = rq->sector; - - blk_put_request(rq); - return ret; -} - -EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn); - static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) { int rw = rq_data_dir(rq); -- cgit v0.10.2 From 40da47e1159b89f2df5c718d2d5e269ced72b541 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 21 Sep 2005 09:55:34 -0700 Subject: [PATCH] ppc64: Build zImage.vmode for G5 zImage.vmode was recently added. It's a version of zImage in which the ELF note section used by open firmware indicates that it requires a virtual mode instance of OF instead of real mode. This allows it to work with Apple OF, and thus is directly bootable (or netbootable) from OF command line. (Unfortunately, pSeries OF sort-of requires real mode and Apple OF sort-of requires virtual mode, and both tend to be unhappy if no notes section specifies the mode at all). However, we forgot to add zImage.vmode to the default G5 build. This fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index 17d2c1e..521c2a5 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile @@ -107,7 +107,7 @@ install: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ defaultimage-$(CONFIG_PPC_PSERIES) := zImage -defaultimage-$(CONFIG_PPC_PMAC) := vmlinux +defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode defaultimage-$(CONFIG_PPC_MAPLE) := zImage defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux KBUILD_IMAGE := $(defaultimage-y) -- cgit v0.10.2 From 8b20f6da20d874a58becc7a08b130c4382ea7325 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Wed, 21 Sep 2005 09:55:35 -0700 Subject: [PATCH] Fix I2O config-osm init to return proper error We currently unregister the config-osm driver if initialization of the legacy ioctl() handlers failed but still return success. We should be returning -EBUSY in this case. Signed-off-by: Deepak Saxena Cc: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index af32ab4..10432f6 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c @@ -56,8 +56,11 @@ static int __init i2o_config_init(void) return -EBUSY; } #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL - if (i2o_config_old_init()) + if (i2o_config_old_init()) { + osm_err("old config handler initialization failed\n"); i2o_driver_unregister(&i2o_config_driver); + return -EBUSY; + } #endif return 0; -- cgit v0.10.2 From f10df6860498c7f52db4f00ff00a1ba334bcfea0 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 09:55:37 -0700 Subject: [PATCH] fix locking comment in unmap_region() That comment is plain wrong (we even take the pagetable lock inside unmap_region()). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/mmap.c b/mm/mmap.c index 8b8e05f..fa11d91 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1640,7 +1640,7 @@ static void unmap_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) /* * Get rid of page table information in the indicated region. * - * Called with the page table lock held. + * Called with the mm semaphore held. */ static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, -- cgit v0.10.2 From f875a1a6650edce859bd21051a22e1c27ac7ea63 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 09:55:37 -0700 Subject: [PATCH] README update from the stone age We have no options which the user can set in the Makefile. Only the EXTRAVERSION, which is also useful in place of the "backup modules" suggestion. We don't have configuration options in the top Makefile. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/README b/README index 76dd780..2b5844d 100644 --- a/README +++ b/README @@ -149,6 +149,9 @@ CONFIGURING the kernel: "make gconfig" X windows (Gtk) based configuration tool. "make oldconfig" Default all questions based on the contents of your existing ./.config file. + "make silentoldconfig" + Like above, but avoids cluttering the screen + with question already answered. NOTES on "make config": - having unnecessary drivers will make the kernel bigger, and can @@ -169,9 +172,6 @@ CONFIGURING the kernel: should probably answer 'n' to the questions for "development", "experimental", or "debugging" features. - - Check the top Makefile for further site-dependent configuration - (default SVGA mode etc). - COMPILING the kernel: - Make sure you have gcc 2.95.3 available. @@ -199,6 +199,9 @@ COMPILING the kernel: are installing a new kernel with the same version number as your working kernel, make a backup of your modules directory before you do a "make modules_install". + In alternative, before compiling, edit your Makefile and change the + "EXTRAVERSION" line - its content is appended to the regular kernel + version. - In order to boot your new kernel, you'll need to copy the kernel image (e.g. .../linux/arch/i386/boot/bzImage after compilation) -- cgit v0.10.2 From 7e871b6c8f1f4fda41e51ef86147facecac3be9f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 09:55:38 -0700 Subject: [PATCH] mm: update stale comment for removal of page->list Update comment for the 2.6.6-rc1 conversion from page->list and address_space->{clean,dirty,locked}_pages to radix tree tagging and ->lru. I've mostly avoided to mention page lists (at least I've shortened the comment). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mm.h b/include/linux/mm.h index 82d7024..0d94c94 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -350,7 +350,8 @@ static inline void put_page(struct page *page) * only one copy in memory, at most, normally. * * For the non-reserved pages, page_count(page) denotes a reference count. - * page_count() == 0 means the page is free. + * page_count() == 0 means the page is free. page->lru is then used for + * freelist management in the buddy allocator. * page_count() == 1 means the page is used for exactly one purpose * (e.g. a private data page of one process). * @@ -376,10 +377,8 @@ static inline void put_page(struct page *page) * attaches, plus 1 if `private' contains something, plus one for * the page cache itself. * - * All pages belonging to an inode are in these doubly linked lists: - * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages; - * using the page->list list_head. These fields are also used for - * freelist managemet (when page_count()==0). + * Instead of keeping dirty/clean pages in per address-space lists, we instead + * now tag pages as dirty/under writeback in the radix tree. * * There is also a per-mapping radix tree mapping index to the page * in memory if present. The tree is rooted at mapping->root. -- cgit v0.10.2 From 7e2cff42cfac27c25202648c5c89f9171e5bc085 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 09:55:39 -0700 Subject: [PATCH] mm: add a note about partially hardcoded VM_* flags Hugh made me note this line for permission checking in mprotect(): if ((newflags & ~(newflags >> 4)) & 0xf) { after figuring out what's that about, I decided it's nasty enough. Btw Hugh itself didn't like the 0xf. We can safely change it to VM_READ|VM_WRITE|VM_EXEC because we never change VM_SHARED, so no need to check that. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Acked-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/mm.h b/include/linux/mm.h index 0d94c94..097b3a3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -136,6 +136,7 @@ extern unsigned int kobjsize(const void *objp); #define VM_EXEC 0x00000004 #define VM_SHARED 0x00000008 +/* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */ #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */ #define VM_MAYWRITE 0x00000020 #define VM_MAYEXEC 0x00000040 diff --git a/mm/mprotect.c b/mm/mprotect.c index e9fbd01..57577f6 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -248,7 +248,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); - if ((newflags & ~(newflags >> 4)) & 0xf) { + /* newflags >> 4 shift VM_MAY% in place of VM_% */ + if ((newflags & ~(newflags >> 4)) & (VM_READ | VM_WRITE | VM_EXEC)) { error = -EACCES; goto out; } -- cgit v0.10.2 From 8f91648dcb0685d58aa046b25c69ce0d5f284f8c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 21 Sep 2005 09:55:40 -0700 Subject: [PATCH] fixup Documentation/DocBook/kernel-hacking.tmpl __FUNCTION__ is the prefered kernel idiom, __func__ is not supported by gcc 2.95 (we actually map __FUNCTION__ to __func__ for more recent compilers, but it should never be used directly) Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index 6367bba..582032e 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl @@ -1105,7 +1105,7 @@ static struct block_device_operations opt_fops = { - Function names as strings (__func__). + Function names as strings (__FUNCTION__). -- cgit v0.10.2 From 4b1ac9ab15c1fc1e0b73d887a0c0cafe92991f97 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 21 Sep 2005 09:55:41 -0700 Subject: [PATCH] skge: add maintainer Add MAINTAINER record for Andrew ;-) Signed-off-by: Stephen Hemminger Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index dc8f3ba..ade7415 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2266,6 +2266,12 @@ M: kristen.c.accardi@intel.com L: pcihpd-discuss@lists.sourceforge.net S: Maintained +SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS +P: Stephen Hemminger +M: shemminger@osdl.org +L: netdev@vger.kernel.org +S: Maintained + SPARC (sparc32): P: William L. Irwin M: wli@holomorphy.com -- cgit v0.10.2 From 7980cbbb30bf044e6f40912a3f6456204ddfc27e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 21 Sep 2005 09:55:43 -0700 Subject: [PATCH] Adds sys_set_mempolicy() in include/linux/syscalls.h Signed-off-by: Eric Dumazet Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 425f58c..a6f03e4 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -508,5 +508,7 @@ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, asmlinkage long sys_ioprio_set(int which, int who, int ioprio); asmlinkage long sys_ioprio_get(int which, int who); +asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, + unsigned long maxnode); #endif -- cgit v0.10.2 From 89d7cbf73e1a85241eb42339f6cb7a429fec178c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 21 Sep 2005 09:55:44 -0700 Subject: [PATCH] update URL for HPET spec. Correct URL for HPET spec. Signed-off-by: Randy Dunlap Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 0969d57..21afa69 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -308,7 +308,7 @@ config HPET_TIMER present. The HPET provides a stable time base on SMP systems, unlike the TSC, but it is more expensive to access, as it is off-chip. You can find the HPET spec at - . + . config X86_PM_TIMER bool "PM timer" -- cgit v0.10.2 From 62a36c43c898d45efcfe3376ea1da6a9a182e1ad Mon Sep 17 00:00:00 2001 From: Stephane Kardas Date: Wed, 21 Sep 2005 09:55:45 -0700 Subject: [PATCH] fat: fix adate During a forensic analysis on the fat file system, I found than the result for the last access date on this file system was different between the stat command and the istat command (package tct-utils). The istat command display a true date (the right windows date) but the stat primitive (so stat, find, ls command) displays a wrong date. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 51b1d15..e2effe2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -300,9 +300,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_blksize = sbi->cluster_size; inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) & ~((loff_t)sbi->cluster_size - 1)) >> 9; - inode->i_mtime.tv_sec = inode->i_atime.tv_sec = + inode->i_mtime.tv_sec = date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); - inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; if (sbi->options.isvfat) { int secs = de->ctime_cs / 100; int csecs = de->ctime_cs % 100; @@ -310,8 +310,11 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate)) + secs; inode->i_ctime.tv_nsec = csecs * 10000000; + inode->i_atime.tv_sec = + date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate)); + inode->i_atime.tv_nsec = 0; } else - inode->i_ctime = inode->i_mtime; + inode->i_ctime = inode->i_atime = inode->i_mtime; return 0; } @@ -513,7 +516,9 @@ retry: raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); if (sbi->options.isvfat) { + __le16 atime; fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); + fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate); raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + inode->i_ctime.tv_nsec / 10000000; } -- cgit v0.10.2 From 972d512a17c1bb7c4b784a9da2ca75745fcc6989 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 21 Sep 2005 12:31:26 -0700 Subject: [IB] Add MAD data field size definitions Clean up code by using enums instead of hard-coded magic numbers. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 2bd8b1c..8f7cef0 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -583,6 +583,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; int timeout; + u32 paylen; rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); @@ -590,11 +591,9 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) if (mad_send_wr->seg_num == 1) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; - rmpp_mad->rmpp_hdr.paylen_newwin = - cpu_to_be32(mad_send_wr->total_seg * - (sizeof(struct ib_rmpp_mad) - - offsetof(struct ib_rmpp_mad, data)) - - mad_send_wr->pad); + paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA - + mad_send_wr->pad; + rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); } else { mad_send_wr->send_wr.num_sge = 2; @@ -608,10 +607,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) if (mad_send_wr->seg_num == mad_send_wr->total_seg) { rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; - rmpp_mad->rmpp_hdr.paylen_newwin = - cpu_to_be32(sizeof(struct ib_rmpp_mad) - - offsetof(struct ib_rmpp_mad, data) - - mad_send_wr->pad); + paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; + rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); } /* 2 seconds for an ACK until we can find the packet lifetime */ diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 53184a3..0e293fe 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -108,6 +108,13 @@ #define IB_QP1_QKEY 0x80010000 #define IB_QP_SET_QKEY 0x80000000 +enum { + IB_MGMT_MAD_DATA = 232, + IB_MGMT_RMPP_DATA = 220, + IB_MGMT_VENDOR_DATA = 216, + IB_MGMT_SA_DATA = 200 +}; + struct ib_mad_hdr { u8 base_version; u8 mgmt_class; @@ -149,20 +156,20 @@ struct ib_sa_hdr { struct ib_mad { struct ib_mad_hdr mad_hdr; - u8 data[232]; + u8 data[IB_MGMT_MAD_DATA]; }; struct ib_rmpp_mad { struct ib_mad_hdr mad_hdr; struct ib_rmpp_hdr rmpp_hdr; - u8 data[220]; + u8 data[IB_MGMT_RMPP_DATA]; }; struct ib_sa_mad { struct ib_mad_hdr mad_hdr; struct ib_rmpp_hdr rmpp_hdr; struct ib_sa_hdr sa_hdr; - u8 data[200]; + u8 data[IB_MGMT_SA_DATA]; } __attribute__ ((packed)); struct ib_vendor_mad { @@ -170,7 +177,7 @@ struct ib_vendor_mad { struct ib_rmpp_hdr rmpp_hdr; u8 reserved; u8 oui[3]; - u8 data[216]; + u8 data[IB_MGMT_VENDOR_DATA]; }; struct ib_class_port_info -- cgit v0.10.2 From f2065e4242e5078d53c521b973c5cd4eae91eca2 Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Wed, 21 Sep 2005 12:33:09 -0700 Subject: [IB] Fix RMPP receive length calculation Based on simplification idea from Sean Hefty Signed-off-by: Hal Rosenstock Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 8f7cef0..e23836d 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -412,8 +412,8 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); data_size = sizeof(struct ib_rmpp_mad) - hdr_size; - pad = data_size - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); - if (pad > data_size || pad < 0) + pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); + if (pad > IB_MGMT_RMPP_DATA || pad < 0) pad = 0; return hdr_size + rmpp_recv->seg_num * data_size - pad; -- cgit v0.10.2 From 6a1ced59b3ac5d1088f597fd0613a724cdf19e2c Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 21 Sep 2005 22:14:05 +0100 Subject: [ARM] 2932/1: Avoid the "noreturn" warning in arch/arm/kernel/traps.c Patch from Catalin Marinas This patch prevents the "noreturn function does return" warning in the __bug() function in arch/arm/kernel/traps.c Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4554c96..e7d22db 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -624,6 +624,9 @@ void __attribute__((noreturn)) __bug(const char *file, int line, void *data) printk(" - extra data = %p", data); printk("\n"); *(int *)0 = 0; + + /* Avoid "noreturn function does return" */ + for (;;); } EXPORT_SYMBOL(__bug); -- cgit v0.10.2 From 68ce1eb54056e4fad6e73968e958b926d28cb0dd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 21 Sep 2005 09:46:54 -0700 Subject: [SCSI] lpfc build fix gcc-2.95.x doesn't do anonymous unions. Signed-off-by: Andrew Morton Signed-off-by: James Bottomley diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 86eaf6d..acae7c4 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -973,10 +973,10 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) if ((phba->fc_flag & FC_FABRIC) || ((phba->fc_topology == TOPOLOGY_LOOP) && (phba->fc_flag & FC_PUBLIC_LOOP))) - node_name = wwn_to_u64(phba->fc_fabparam.nodeName.wwn); + node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); else /* fabric is local port if there is no F/FL_Port */ - node_name = wwn_to_u64(phba->fc_nodename.wwn); + node_name = wwn_to_u64(phba->fc_nodename.u.wwn); spin_unlock_irq(shost->host_lock); @@ -1110,7 +1110,7 @@ lpfc_get_starget_node_name(struct scsi_target *starget) /* Search the mapped list for this target ID */ list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { if (starget->id == ndlp->nlp_sid) { - node_name = wwn_to_u64(ndlp->nlp_nodename.wwn); + node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); break; } } @@ -1131,7 +1131,7 @@ lpfc_get_starget_port_name(struct scsi_target *starget) /* Search the mapped list for this target ID */ list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { if (starget->id == ndlp->nlp_sid) { - port_name = wwn_to_u64(ndlp->nlp_portname.wwn); + port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); break; } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 4fb8eb0..56052f4 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1019,8 +1019,8 @@ lpfc_register_remote_port(struct lpfc_hba * phba, struct fc_rport_identifiers rport_ids; /* Remote port has reappeared. Re-register w/ FC transport */ - rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.wwn); - rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.wwn); + rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); + rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); rport_ids.port_id = ndlp->nlp_DID; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; if (ndlp->nlp_type & NLP_FCP_TARGET) diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 047a87c..86c4198 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -280,9 +280,9 @@ struct lpfc_name { #define NAME_CCITT_GR_TYPE 0xE uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */ uint8_t IEEE[6]; /* FC IEEE address */ - }; + } s; uint8_t wwn[8]; - }; + } u; }; struct csp { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 454058f..0856ff7 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -285,7 +285,7 @@ lpfc_config_port_post(struct lpfc_hba * phba) if (phba->SerialNumber[0] == 0) { uint8_t *outptr; - outptr = (uint8_t *) & phba->fc_nodename.IEEE[0]; + outptr = &phba->fc_nodename.u.s.IEEE[0]; for (i = 0; i < 12; i++) { status = *outptr++; j = ((status & 0xf0) >> 4); @@ -1523,8 +1523,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) * Must done after lpfc_sli_hba_setup() */ - fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.wwn); - fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.wwn); + fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn); + fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn); fc_host_supported_classes(host) = FC_COS_CLASS3; memset(fc_host_supported_fc4s(host), 0, -- cgit v0.10.2 From c51179fb0c77ad91df5825f8f7eb670da97e137e Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:37:14 +0200 Subject: [PATCH] uml: adapt asm/futex.h to our arch Follow up to 4732efbeb997189d9f9b04708dc26bf8613ed721 - uml must just reuse as-is the backing architecture support. There is a micro-fixup is needed for the included file, which won't affect i386 behaviour at all. I've not tested compilation on x86_64, only on x86, but the code is almost the same except the culprit test, so everything should be ok on x86_64 too. Cc: Jakub Jelinek Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index 44b9db8..e7a271d 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h @@ -61,7 +61,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) if (op == FUTEX_OP_SET) __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); else { -#ifndef CONFIG_X86_BSWAP +#if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML) if (boot_cpu_data.x86 == 3) ret = -ENOSYS; else diff --git a/include/asm-um/futex.h b/include/asm-um/futex.h index 2cac5ec..142ee2d 100644 --- a/include/asm-um/futex.h +++ b/include/asm-um/futex.h @@ -1,53 +1,12 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#ifdef __KERNEL__ +#ifndef __UM_FUTEX_H +#define __UM_FUTEX_H #include #include +#include +#include #include -static inline int -futex_atomic_op_inuser (int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - case FUTEX_OP_ADD: - case FUTEX_OP_OR: - case FUTEX_OP_ANDN: - case FUTEX_OP_XOR: - default: - ret = -ENOSYS; - } +#include "asm/arch/futex.h" - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif #endif -- cgit v0.10.2 From 676067cfeaa16f6f338e067e83ce4733b41c0b24 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:38:09 +0200 Subject: [PATCH] Remove unused var from asm/futex.h As recently done by Russell King for ARM, commit 4732efbeb997189d9f9b04708dc26bf8613ed721 introduces a generic asm/futex.h copied along most arches, which includes a "-ENOSYS support" to be changed if needed. However, it includes an unused var (taken from the "real" version) which GCC warns about. Remove it from all arches having that file version (i.e. same GIT id). $ git-diff-tree -r HEAD and $ git-ls-tree -r HEAD include/|grep 9feff4ce1424bc390608326240be369eb13aa648 may be more interesting than looking at the patch itself, to make sure I've just copied the arm header to all other archs having the original dummy version of this file. Cc: Jakub Jelinek Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/include/asm-alpha/futex.h b/include/asm-alpha/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-alpha/futex.h +++ b/include/asm-alpha/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-arm26/futex.h b/include/asm-arm26/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-arm26/futex.h +++ b/include/asm-arm26/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-cris/futex.h b/include/asm-cris/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-cris/futex.h +++ b/include/asm-cris/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-frv/futex.h +++ b/include/asm-frv/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-h8300/futex.h b/include/asm-h8300/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-h8300/futex.h +++ b/include/asm-h8300/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-ia64/futex.h +++ b/include/asm-ia64/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-m32r/futex.h b/include/asm-m32r/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-m32r/futex.h +++ b/include/asm-m32r/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-m68k/futex.h b/include/asm-m68k/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-m68k/futex.h +++ b/include/asm-m68k/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-m68knommu/futex.h b/include/asm-m68knommu/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-m68knommu/futex.h +++ b/include/asm-m68knommu/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-parisc/futex.h +++ b/include/asm-parisc/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-ppc/futex.h b/include/asm-ppc/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-ppc/futex.h +++ b/include/asm-ppc/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-s390/futex.h +++ b/include/asm-s390/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-sh/futex.h +++ b/include/asm-sh/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-sh64/futex.h b/include/asm-sh64/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-sh64/futex.h +++ b/include/asm-sh64/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-sparc/futex.h +++ b/include/asm-sparc/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-sparc64/futex.h +++ b/include/asm-sparc64/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h index 2cac5ec..9feff4ce 100644 --- a/include/asm-v850/futex.h +++ b/include/asm-v850/futex.h @@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret, tem; + int oldval = 0, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; -- cgit v0.10.2 From 76629ac154aacfec8883954c3ff9871905d2fb8e Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:38:33 +0200 Subject: [PATCH] uml: remove verify_area_{tt,skas} When removing verify_area, verify_area_{tt,skas} were forgotten. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 6ee3f39..7da0c2d 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h @@ -18,12 +18,6 @@ ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) -static inline int verify_area_skas(int type, const void __user * addr, - unsigned long size) -{ - return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); -} - extern int copy_from_user_skas(void *to, const void __user *from, int n); extern int copy_to_user_skas(void __user *to, const void *from, int n); extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index aa6db38..dc2ebfa 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h @@ -33,12 +33,6 @@ extern unsigned long uml_physmem; (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ (under_task_size(addr, size) || is_stack(addr, size)))) -static inline int verify_area_tt(int type, const void __user * addr, - unsigned long size) -{ - return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); -} - extern unsigned long get_fault_addr(void); extern int __do_copy_from_user(void *to, const void *from, int n, -- cgit v0.10.2 From 36decba90b184a25b7f77fb7df1612125cc41ac5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:38:57 +0200 Subject: [PATCH] uml: fix modify_ldt - missing break in switch I am a lamer :-(. Luckily, Luo Xin performed LTP testing and found this failure. Btw, the fact that the patch in which I introduced this was merged shows that: a) I'm really trusted by people b) sometimes they're wrong about point a). c) lack of time for reviewers. CC: Luo Xin Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index bd3c34a..36b5c2c 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -83,6 +83,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) goto out; } p = buf; + break; default: res = -ENOSYS; goto out; -- cgit v0.10.2 From 8e5cb35a60c8792ffc3ba89ea66ebdd3c2f01cb1 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:39:14 +0200 Subject: [PATCH] uml: fix uname output on 32-bit binary on 64-bit host Translate uname output taken from the host if needed. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index a25f3ea..41d17c7 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -128,6 +128,12 @@ void setup_machinename(char *machine_out) struct utsname host; uname(&host); +#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT) + if (!strcmp(host.machine, "x86_64")) { + strcpy(machine_out, "i686"); + return; + } +#endif strcpy(machine_out, host.machine); } -- cgit v0.10.2 From fd7481047882eaa0a692a545d5f8419612ece1b0 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:39:32 +0200 Subject: [PATCH] uml: Fix conflict between libc and ipv6 gcc is now complaining during link on some hosts - fix it as for other things. Reported by Antoine Martin . Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/Makefile b/arch/um/Makefile index ce98726..5b5af95 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -53,9 +53,13 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) # -Dvmap=kernel_vmap affects everything, and prevents anything from # referencing the libpcap.o symbol so named. +# +# Same things for in6addr_loopback - found in libc. CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ - $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap + $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ + -Din6addr_loopback=kernel_in6addr_loopback + AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) -- cgit v0.10.2 From 41c79dc3825545d9aa2d5e5b1a99f8faabf51455 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:39:47 +0200 Subject: [PATCH] uml: fix bogus HOST_ELF_CLASS symbol name Even if with a bit of misunderstanding, Al fixed this in commit 95608261dae863bc43292e6fbd946a3abd3aa49f. Well, the symbol was intended to come from userspace (it exists there on normal host), but since some hosts may miss that, using the kernel one is just as fine. However, rename it to be named consistently with the rest. Actually, he missed converting ELFCLASS32 to coming from kernel headers. For consistence, add ELFCLASS64 too. Cc: Al Viro Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 0aa6209..782ac3a 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h @@ -12,4 +12,6 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); DEFINE_STR(UM_KERN_INFO, KERN_INFO); DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); -DEFINE(HOST_ELF_CLASS, ELF_CLASS); +DEFINE(UM_ELF_CLASS, ELF_CLASS); +DEFINE(UM_ELFCLASS32, ELFCLASS32); +DEFINE(UM_ELFCLASS64, ELFCLASS64); diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index e770cb0..ab33cb3 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -14,7 +14,8 @@ #include "mem_user.h" #include -#if HOST_ELF_CLASS == ELFCLASS32 +/* Use the one from the kernel - the host may miss it, if having old headers. */ +#if UM_ELF_CLASS == UM_ELFCLASS32 typedef Elf32_auxv_t elf_auxv_t; #else typedef Elf64_auxv_t elf_auxv_t; -- cgit v0.10.2 From ae756df8ddd00a30bb3bdf6774b514c096dda4a4 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:40:10 +0200 Subject: [PATCH] uml: readd removed unistd.h inclusion Readd this header (deleted in 60d339f6fe0831060600c62418b71a62ad26c281). A warning is spit out here about undeclared getpgrp(). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index d32413e..d9c5238 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -3,6 +3,7 @@ * Licensed under the GPL */ +#include #include #include #include -- cgit v0.10.2 From a46c9047642d70f5619e4a14129d74dd1f6ea74f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:40:29 +0200 Subject: [PATCH] uml: comment about cast build fix Explain why the casting we do to silence this warning is indeed safe. It is because the field we're casting from, though being 64-bit wide, was filled with a pointer in first place by ourselves. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 298d563..f6e6402 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -144,6 +144,7 @@ static int aio_thread(void *arg) "errno = %d\n", errno); } else { + /* This is safe as we've just a pointer here. */ aio = (struct aio_context *) (long) event.data; if(update_aio(aio, event.res)){ do_aio(ctx, aio); -- cgit v0.10.2 From efb0372bbaf5b829ff8c39db372779928af542a7 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Wed, 21 Sep 2005 18:40:49 +0200 Subject: [PATCH] uml: fix compile warning after consolidation patch The header declaring this function wasn't included, so the function declaration was totally bogus wrt. the proto - even if this wasn't going to fail at all. It was so bad that the compile warning I got was "control reaches end of non-void function", i.e. missing return. Actually, this has been there for ages, the consolidation patch just added the warning which was needed to clean it up. Nice. Really. Cc: Allan Graves Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 0de05a268..cfaa373 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -23,10 +23,11 @@ #include "mem_user.h" #include "tlb.h" #include "mode.h" +#include "mode_kern.h" #include "init.h" #include "tt.h" -int switch_to_tt(void *prev, void *next, void *last) +void switch_to_tt(void *prev, void *next) { struct task_struct *from, *to, *prev_sched; unsigned long flags; -- cgit v0.10.2 From 2a7e2990340a1c42321d79dc99755683ea5a1026 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Sep 2005 18:50:51 -0700 Subject: [SPARC64]: Move kernel TLB miss handling into a seperate file. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S index ded2fed..702d349 100644 --- a/arch/sparc64/kernel/dtlb_base.S +++ b/arch/sparc64/kernel/dtlb_base.S @@ -71,7 +71,7 @@ from_tl1_trap: rdpr %tl, %g5 ! For TL==3 test CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset - be,pn %xcc, 3f ! Yep, special processing + be,pn %xcc, kvmap ! Yep, special processing CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset cmp %g5, 4 ! Last trap level? be,pn %xcc, longpath ! Yep, cannot risk VPTE miss @@ -83,9 +83,9 @@ from_tl1_trap: nop ! Delay-slot 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB retry ! Trap return -3: brlz,pt %g4, 9b ! Kernel virtual map? - xor %g2, %g4, %g5 ! Finish bit twiddles - ba,a,pt %xcc, kvmap ! Yep, go check for obp/vmalloc + nop + nop + nop /* DTLB ** ICACHE line 3: winfixups+real_faults */ longpath: diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index b483495..45cd3bb 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -30,159 +30,6 @@ .text .align 32 - .globl sparc64_vpte_patchme1 - .globl sparc64_vpte_patchme2 -/* - * On a second level vpte miss, check whether the original fault is to the OBP - * range (note that this is only possible for instruction miss, data misses to - * obp range do not use vpte). If so, go back directly to the faulting address. - * This is because we want to read the tpc, otherwise we have no way of knowing - * the 8k aligned faulting address if we are using >8k kernel pagesize. This - * also ensures no vpte range addresses are dropped into tlb while obp is - * executing (see inherit_locked_prom_mappings() rant). - */ -sparc64_vpte_nucleus: - /* Note that kvmap below has verified that the address is - * in the range MODULES_VADDR --> VMALLOC_END already. So - * here we need only check if it is an OBP address or not. - */ - sethi %hi(LOW_OBP_ADDRESS), %g5 - cmp %g4, %g5 - blu,pn %xcc, sparc64_vpte_patchme1 - mov 0x1, %g5 - sllx %g5, 32, %g5 - cmp %g4, %g5 - blu,pn %xcc, obp_iaddr_patch - nop - - /* These two instructions are patched by paginig_init(). */ -sparc64_vpte_patchme1: - sethi %hi(0), %g5 -sparc64_vpte_patchme2: - or %g5, %lo(0), %g5 - - /* With kernel PGD in %g5, branch back into dtlb_backend. */ - ba,pt %xcc, sparc64_kpte_continue - andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */ - -vpte_noent: - /* Restore previous TAG_ACCESS, %g5 is zero, and we will - * skip over the trap instruction so that the top level - * TLB miss handler will thing this %g5 value is just an - * invalid PTE, thus branching to full fault processing. - */ - mov TLB_SFSR, %g1 - stxa %g4, [%g1 + %g1] ASI_DMMU - done - - .globl obp_iaddr_patch -obp_iaddr_patch: - /* These two instructions patched by inherit_prom_mappings(). */ - sethi %hi(0), %g5 - or %g5, %lo(0), %g5 - - /* Behave as if we are at TL0. */ - wrpr %g0, 1, %tl - rdpr %tpc, %g4 /* Find original faulting iaddr */ - srlx %g4, 13, %g4 /* Throw out context bits */ - sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */ - - /* Restore previous TAG_ACCESS. */ - mov TLB_SFSR, %g1 - stxa %g4, [%g1 + %g1] ASI_IMMU - - /* Get PMD offset. */ - srlx %g4, 23, %g6 - and %g6, 0x7ff, %g6 - sllx %g6, 2, %g6 - - /* Load PMD, is it valid? */ - lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - sllx %g5, 11, %g5 - - /* Get PTE offset. */ - srlx %g4, 13, %g6 - and %g6, 0x3ff, %g6 - sllx %g6, 3, %g6 - - /* Load PTE. */ - ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brgez,pn %g5, longpath - nop - - /* TLB load and return from trap. */ - stxa %g5, [%g0] ASI_ITLB_DATA_IN - retry - - .globl obp_daddr_patch -obp_daddr_patch: - /* These two instructions patched by inherit_prom_mappings(). */ - sethi %hi(0), %g5 - or %g5, %lo(0), %g5 - - /* Get PMD offset. */ - srlx %g4, 23, %g6 - and %g6, 0x7ff, %g6 - sllx %g6, 2, %g6 - - /* Load PMD, is it valid? */ - lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - sllx %g5, 11, %g5 - - /* Get PTE offset. */ - srlx %g4, 13, %g6 - and %g6, 0x3ff, %g6 - sllx %g6, 3, %g6 - - /* Load PTE. */ - ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brgez,pn %g5, longpath - nop - - /* TLB load and return from trap. */ - stxa %g5, [%g0] ASI_DTLB_DATA_IN - retry - -/* - * On a first level data miss, check whether this is to the OBP range (note - * that such accesses can be made by prom, as well as by kernel using - * prom_getproperty on "address"), and if so, do not use vpte access ... - * rather, use information saved during inherit_prom_mappings() using 8k - * pagesize. - */ - .align 32 -kvmap: - sethi %hi(MODULES_VADDR), %g5 - cmp %g4, %g5 - blu,pn %xcc, longpath - mov (VMALLOC_END >> 24), %g5 - sllx %g5, 24, %g5 - cmp %g4, %g5 - bgeu,pn %xcc, longpath - nop - -kvmap_check_obp: - sethi %hi(LOW_OBP_ADDRESS), %g5 - cmp %g4, %g5 - blu,pn %xcc, kvmap_vmalloc_addr - mov 0x1, %g5 - sllx %g5, 32, %g5 - cmp %g4, %g5 - blu,pn %xcc, obp_daddr_patch - nop - -kvmap_vmalloc_addr: - /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ - ldxa [%g3 + %g6] ASI_N, %g5 - brgez,pn %g5, longpath - nop - - /* PTE is valid, load into TLB and return from trap. */ - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB - retry - /* This is trivial with the new code... */ .globl do_fpdis do_fpdis: diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 1fa06c4..dc3551f 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -762,6 +762,7 @@ bootup_user_stack_end: swapper_pg_dir: .word 0 +#include "ktlb.S" #include "etrap.S" #include "rtrap.S" #include "winfixup.S" diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S new file mode 100644 index 0000000..b717679 --- /dev/null +++ b/arch/sparc64/kernel/ktlb.S @@ -0,0 +1,174 @@ +/* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling. + * + * Copyright (C) 1995, 1997, 2005 David S. Miller + * Copyright (C) 1996 Eddie C. Dost (ecd@brainaid.de) + * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz) +*/ + +#include +#include +#include +#include +#include + + .text + .align 32 + + .globl sparc64_vpte_patchme1 + .globl sparc64_vpte_patchme2 +/* + * On a second level vpte miss, check whether the original fault is to the OBP + * range (note that this is only possible for instruction miss, data misses to + * obp range do not use vpte). If so, go back directly to the faulting address. + * This is because we want to read the tpc, otherwise we have no way of knowing + * the 8k aligned faulting address if we are using >8k kernel pagesize. This + * also ensures no vpte range addresses are dropped into tlb while obp is + * executing (see inherit_locked_prom_mappings() rant). + */ +sparc64_vpte_nucleus: + /* Note that kvmap below has verified that the address is + * in the range MODULES_VADDR --> VMALLOC_END already. So + * here we need only check if it is an OBP address or not. + */ + sethi %hi(LOW_OBP_ADDRESS), %g5 + cmp %g4, %g5 + blu,pn %xcc, sparc64_vpte_patchme1 + mov 0x1, %g5 + sllx %g5, 32, %g5 + cmp %g4, %g5 + blu,pn %xcc, obp_iaddr_patch + nop + + /* These two instructions are patched by paginig_init(). */ +sparc64_vpte_patchme1: + sethi %hi(0), %g5 +sparc64_vpte_patchme2: + or %g5, %lo(0), %g5 + + /* With kernel PGD in %g5, branch back into dtlb_backend. */ + ba,pt %xcc, sparc64_kpte_continue + andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */ + +vpte_noent: + /* Restore previous TAG_ACCESS, %g5 is zero, and we will + * skip over the trap instruction so that the top level + * TLB miss handler will thing this %g5 value is just an + * invalid PTE, thus branching to full fault processing. + */ + mov TLB_SFSR, %g1 + stxa %g4, [%g1 + %g1] ASI_DMMU + done + + .globl obp_iaddr_patch +obp_iaddr_patch: + /* These two instructions patched by inherit_prom_mappings(). */ + sethi %hi(0), %g5 + or %g5, %lo(0), %g5 + + /* Behave as if we are at TL0. */ + wrpr %g0, 1, %tl + rdpr %tpc, %g4 /* Find original faulting iaddr */ + srlx %g4, 13, %g4 /* Throw out context bits */ + sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */ + + /* Restore previous TAG_ACCESS. */ + mov TLB_SFSR, %g1 + stxa %g4, [%g1 + %g1] ASI_IMMU + + /* Get PMD offset. */ + srlx %g4, 23, %g6 + and %g6, 0x7ff, %g6 + sllx %g6, 2, %g6 + + /* Load PMD, is it valid? */ + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brz,pn %g5, longpath + sllx %g5, 11, %g5 + + /* Get PTE offset. */ + srlx %g4, 13, %g6 + and %g6, 0x3ff, %g6 + sllx %g6, 3, %g6 + + /* Load PTE. */ + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brgez,pn %g5, longpath + nop + + /* TLB load and return from trap. */ + stxa %g5, [%g0] ASI_ITLB_DATA_IN + retry + + .globl obp_daddr_patch +obp_daddr_patch: + /* These two instructions patched by inherit_prom_mappings(). */ + sethi %hi(0), %g5 + or %g5, %lo(0), %g5 + + /* Get PMD offset. */ + srlx %g4, 23, %g6 + and %g6, 0x7ff, %g6 + sllx %g6, 2, %g6 + + /* Load PMD, is it valid? */ + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brz,pn %g5, longpath + sllx %g5, 11, %g5 + + /* Get PTE offset. */ + srlx %g4, 13, %g6 + and %g6, 0x3ff, %g6 + sllx %g6, 3, %g6 + + /* Load PTE. */ + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brgez,pn %g5, longpath + nop + + /* TLB load and return from trap. */ + stxa %g5, [%g0] ASI_DTLB_DATA_IN + retry + +/* + * On a first level data miss, check whether this is to the OBP range (note + * that such accesses can be made by prom, as well as by kernel using + * prom_getproperty on "address"), and if so, do not use vpte access ... + * rather, use information saved during inherit_prom_mappings() using 8k + * pagesize. + */ + .align 32 +kvmap: + brlz,pt %g4, kvmap_load + xor %g2, %g4, %g5 + +kvmap_nonlinear: + sethi %hi(MODULES_VADDR), %g5 + cmp %g4, %g5 + blu,pn %xcc, longpath + mov (VMALLOC_END >> 24), %g5 + sllx %g5, 24, %g5 + cmp %g4, %g5 + bgeu,pn %xcc, longpath + nop + +kvmap_check_obp: + sethi %hi(LOW_OBP_ADDRESS), %g5 + cmp %g4, %g5 + blu,pn %xcc, kvmap_vmalloc_addr + mov 0x1, %g5 + sllx %g5, 32, %g5 + cmp %g4, %g5 + blu,pn %xcc, obp_daddr_patch + nop + +kvmap_vmalloc_addr: + /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ + ldxa [%g3 + %g6] ASI_N, %g5 + brgez,pn %g5, longpath + nop + +kvmap_load: + /* PTE is valid, load into TLB and return from trap. */ + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB + retry -- cgit v0.10.2 From 552709d5aee9145f325bf07348fb299e84b2e5b3 Mon Sep 17 00:00:00 2001 From: "nsxfreddy@gmail.com" Date: Wed, 21 Sep 2005 14:18:04 -0500 Subject: [PATCH] bonding: Fix link monitor capability check (was skge: set mac address oops with bonding) Fix bond_enslave link monitoring warning to check use_carrier status and ethtool_ops in addition to do_ioctl. This version checks ethtool_ops as well as do_ioctl, and also uses the per-bond params.use_carrier instead of the global use_carrier. Signed-off-by: Jason R. Martin Signed-off-by: Jeff Garzik diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 90449a0..6d00c3d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1653,7 +1653,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de int old_features = bond_dev->features; int res = 0; - if (slave_dev->do_ioctl == NULL) { + if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && + slave_dev->do_ioctl == NULL) { printk(KERN_WARNING DRV_NAME ": Warning : no link monitoring support for %s\n", slave_dev->name); -- cgit v0.10.2 From 059deb693ec191e563ec69533d24f3feff0b78cd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Sep 2005 19:23:48 -0700 Subject: [SPARC64]: Kill SZ_BITS define from dtlb_backend.S This is just a replica of the existing _PAGE_SZBITS, and thus unnecessary. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/dtlb_backend.S b/arch/sparc64/kernel/dtlb_backend.S index 5385228..acc889a 100644 --- a/arch/sparc64/kernel/dtlb_backend.S +++ b/arch/sparc64/kernel/dtlb_backend.S @@ -9,17 +9,7 @@ #include #include -#if PAGE_SHIFT == 13 -#define SZ_BITS _PAGE_SZ8K -#elif PAGE_SHIFT == 16 -#define SZ_BITS _PAGE_SZ64K -#elif PAGE_SHIFT == 19 -#define SZ_BITS _PAGE_SZ512K -#elif PAGE_SHIFT == 22 -#define SZ_BITS _PAGE_SZ4MB -#endif - -#define VALID_SZ_BITS (_PAGE_VALID | SZ_BITS) +#define VALID_SZ_BITS (_PAGE_VALID | _PAGE_SZBITS) #define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P ) #define VPTE_SHIFT (PAGE_SHIFT - 3) @@ -163,7 +153,6 @@ sparc64_vpte_continue: stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS retry ! Load PTE once again -#undef SZ_BITS #undef VALID_SZ_BITS #undef VPTE_SHIFT #undef VPTE_BITS -- cgit v0.10.2 From c3f8be961808313a502c67d59e2b7f930477faf3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 19 Sep 2005 15:37:34 -0700 Subject: [PATCH] skge: expand ethtool debug register dump Expand the returned data for ethtool debug access to include all of the mapped PCI area; except for the small set of registers that are for diagnostic RAM access. Access to those registers will hang the system. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 0208258..62e2ae0 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -105,41 +105,28 @@ static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 }; -/* Don't need to look at whole 16K. - * last interesting register is descriptor poll timer. - */ -#define SKGE_REGS_LEN (29*128) - static int skge_get_regs_len(struct net_device *dev) { - return SKGE_REGS_LEN; + return 0x4000; } /* - * Returns copy of control register region - * I/O region is divided into banks and certain regions are unreadable + * Returns copy of whole control register region + * Note: skip RAM address register because accessing it will + * cause bus hangs! */ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) { const struct skge_port *skge = netdev_priv(dev); - unsigned long offs; const void __iomem *io = skge->hw->regs; - static const unsigned long bankmap - = (1<<0) | (1<<2) | (1<<8) | (1<<9) - | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16) - | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23) - | (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28); regs->version = 1; - for (offs = 0; offs < regs->len; offs += 128) { - u32 len = min_t(u32, 128, regs->len - offs); + memset(p, 0, regs->len); + memcpy_fromio(p, io, B3_RAM_ADDR); - if (bankmap & (1<<(offs/128))) - memcpy_fromio(p + offs, io + offs, len); - else - memset(p + offs, 0, len); - } + memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, + regs->len - B3_RI_WTO_R1); } /* Wake on Lan only supported on Yukon chps with rev 1 or above */ -- cgit v0.10.2 From 383181ac7e59542ff47e2b81f7e4c40aba39b30b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 19 Sep 2005 15:37:16 -0700 Subject: [PATCH] skge: check length from PHY Cleanup receive buffer allocation and management, Add more error handling checks from PHY and bump version. Signed-off-by: Jeff Garzik diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 62e2ae0..ae1996a 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -42,7 +42,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.0" +#define DRV_VERSION "1.1" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -762,17 +762,6 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base) return 0; } -static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size) -{ - struct sk_buff *skb = dev_alloc_skb(size); - - if (likely(skb)) { - skb->dev = dev; - skb_reserve(skb, NET_IP_ALIGN); - } - return skb; -} - /* Allocate and setup a new buffer for receiving */ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, struct sk_buff *skb, unsigned int bufsize) @@ -845,16 +834,17 @@ static int skge_rx_fill(struct skge_port *skge) { struct skge_ring *ring = &skge->rx_ring; struct skge_element *e; - unsigned int bufsize = skge->rx_buf_size; e = ring->start; do { - struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize); + struct sk_buff *skb; + skb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); if (!skb) return -ENOMEM; - skge_rx_setup(skge, e, skb, bufsize); + skb_reserve(skb, NET_IP_ALIGN); + skge_rx_setup(skge, e, skb, skge->rx_buf_size); } while ( (e = e->next) != ring->start); ring->to_clean = ring->start; @@ -2429,6 +2419,14 @@ static void yukon_set_multicast(struct net_device *dev) gma_write16(hw, port, GM_RX_CTRL, reg); } +static inline u16 phy_length(const struct skge_hw *hw, u32 status) +{ + if (hw->chip_id == CHIP_ID_GENESIS) + return status >> XMR_FS_LEN_SHIFT; + else + return status >> GMR_FS_LEN_SHIFT; +} + static inline int bad_phy_status(const struct skge_hw *hw, u32 status) { if (hw->chip_id == CHIP_ID_GENESIS) @@ -2438,80 +2436,99 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status) (status & GMR_FS_RX_OK) == 0; } -static void skge_rx_error(struct skge_port *skge, int slot, - u32 control, u32 status) -{ - if (netif_msg_rx_err(skge)) - printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n", - skge->netdev->name, slot, control, status); - - if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) - skge->net_stats.rx_length_errors++; - else if (skge->hw->chip_id == CHIP_ID_GENESIS) { - if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) - skge->net_stats.rx_length_errors++; - if (status & XMR_FS_FRA_ERR) - skge->net_stats.rx_frame_errors++; - if (status & XMR_FS_FCS_ERR) - skge->net_stats.rx_crc_errors++; - } else { - if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) - skge->net_stats.rx_length_errors++; - if (status & GMR_FS_FRAGMENT) - skge->net_stats.rx_frame_errors++; - if (status & GMR_FS_CRC_ERR) - skge->net_stats.rx_crc_errors++; - } -} /* Get receive buffer from descriptor. * Handles copy of small buffers and reallocation failures */ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, struct skge_element *e, - unsigned int len) + u32 control, u32 status, u16 csum) { - struct sk_buff *nskb, *skb; + struct sk_buff *skb; + u16 len = control & BMU_BBC; + + if (unlikely(netif_msg_rx_status(skge))) + printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n", + skge->netdev->name, e - skge->rx_ring.start, + status, len); + + if (len > skge->rx_buf_size) + goto error; + + if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) + goto error; + + if (bad_phy_status(skge->hw, status)) + goto error; + + if (phy_length(skge->hw, status) != len) + goto error; if (len < RX_COPY_THRESHOLD) { - nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN); - if (unlikely(!nskb)) - return NULL; + skb = dev_alloc_skb(len + 2); + if (!skb) + goto resubmit; + skb_reserve(skb, 2); pci_dma_sync_single_for_cpu(skge->hw->pdev, pci_unmap_addr(e, mapaddr), len, PCI_DMA_FROMDEVICE); - memcpy(nskb->data, e->skb->data, len); + memcpy(skb->data, e->skb->data, len); pci_dma_sync_single_for_device(skge->hw->pdev, pci_unmap_addr(e, mapaddr), len, PCI_DMA_FROMDEVICE); - - if (skge->rx_csum) { - struct skge_rx_desc *rd = e->desc; - nskb->csum = le16_to_cpu(rd->csum2); - nskb->ip_summed = CHECKSUM_HW; - } skge_rx_reuse(e, skge->rx_buf_size); - return nskb; } else { - nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size); - if (unlikely(!nskb)) - return NULL; + struct sk_buff *nskb; + nskb = dev_alloc_skb(skge->rx_buf_size + NET_IP_ALIGN); + if (!nskb) + goto resubmit; pci_unmap_single(skge->hw->pdev, pci_unmap_addr(e, mapaddr), pci_unmap_len(e, maplen), PCI_DMA_FROMDEVICE); skb = e->skb; - if (skge->rx_csum) { - struct skge_rx_desc *rd = e->desc; - skb->csum = le16_to_cpu(rd->csum2); - skb->ip_summed = CHECKSUM_HW; - } - + prefetch(skb->data); skge_rx_setup(skge, e, nskb, skge->rx_buf_size); - return skb; } + + skb_put(skb, len); + skb->dev = skge->netdev; + if (skge->rx_csum) { + skb->csum = csum; + skb->ip_summed = CHECKSUM_HW; + } + + skb->protocol = eth_type_trans(skb, skge->netdev); + + return skb; +error: + + if (netif_msg_rx_err(skge)) + printk(KERN_DEBUG PFX "%s: rx err, slot %td control 0x%x status 0x%x\n", + skge->netdev->name, e - skge->rx_ring.start, + control, status); + + if (skge->hw->chip_id == CHIP_ID_GENESIS) { + if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) + skge->net_stats.rx_length_errors++; + if (status & XMR_FS_FRA_ERR) + skge->net_stats.rx_frame_errors++; + if (status & XMR_FS_FCS_ERR) + skge->net_stats.rx_crc_errors++; + } else { + if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) + skge->net_stats.rx_length_errors++; + if (status & GMR_FS_FRAGMENT) + skge->net_stats.rx_frame_errors++; + if (status & GMR_FS_CRC_ERR) + skge->net_stats.rx_crc_errors++; + } + +resubmit: + skge_rx_reuse(e, skge->rx_buf_size); + return NULL; } @@ -2527,32 +2544,16 @@ static int skge_poll(struct net_device *dev, int *budget) for (e = ring->to_clean; work_done < to_do; e = e->next) { struct skge_rx_desc *rd = e->desc; struct sk_buff *skb; - u32 control, len, status; + u32 control; rmb(); control = rd->control; if (control & BMU_OWN) break; - len = control & BMU_BBC; - status = rd->status; - - if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF) - || bad_phy_status(hw, status))) { - skge_rx_error(skge, e - ring->start, control, status); - skge_rx_reuse(e, skge->rx_buf_size); - continue; - } - - if (netif_msg_rx_status(skge)) - printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n", - dev->name, e - ring->start, rd->status, len); - - skb = skge_rx_get(skge, e, len); + skb = skge_rx_get(skge, e, control, rd->status, + le16_to_cpu(rd->csum2)); if (likely(skb)) { - skb_put(skb, len); - skb->protocol = eth_type_trans(skb, dev); - dev->last_rx = jiffies; netif_receive_skb(skb); diff --git a/drivers/net/skge.h b/drivers/net/skge.h index efbf98c..72c175b 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h @@ -953,6 +953,7 @@ enum { */ enum { XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */ + XMR_FS_LEN_SHIFT = 18, XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/ XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/ XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */ @@ -1868,6 +1869,7 @@ enum { /* Receive Frame Status Encoding */ enum { GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ + GMR_FS_LEN_SHIFT = 16, GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */ GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */ GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */ -- cgit v0.10.2 From 0b50f81d5a63428f131ff20596f4e3d473e5b94f Mon Sep 17 00:00:00 2001 From: Tommy Christensen Date: Wed, 21 Sep 2005 12:13:57 -0700 Subject: [PATCH] r8169: call proper VLAN receive function vlan_hwaccel_rx should be used when in interrupt context. Fixes bug http://bugzilla.kernel.org/show_bug.cgi?id=5284 Signed-off-by: Tommy S. Christensen Cc: Francois Romieu Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f0471d1..f9223c1 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -100,11 +100,11 @@ VERSION 2.2LK <2005/01/25> #ifdef CONFIG_R8169_NAPI #define rtl8169_rx_skb netif_receive_skb -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb #define rtl8169_rx_quota(count, quota) min(count, quota) #else #define rtl8169_rx_skb netif_rx -#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx #define rtl8169_rx_quota(count, quota) count #endif -- cgit v0.10.2 From e86ee6682b649183c11013a98be02f25e9ae399d Mon Sep 17 00:00:00 2001 From: Andy Currid Date: Mon, 19 Sep 2005 06:17:52 -0700 Subject: [PATCH] Add NVIDIA device ID in sata_nv Signed-off-by: Andy Currid Signed-off-by: Jeff Garzik diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index a1d62de..c05653c 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -158,6 +158,8 @@ static struct pci_device_id nv_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f6c1a14..cb414ea 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1267,7 +1267,8 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE 0x036E -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x036F +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA 0x037E +#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2 0x037F #define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268 #define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269 #define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B -- cgit v0.10.2 From 1ac4f5ebaa496a23ab4a148c9864d7e30a6c6cd3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Sep 2005 21:49:32 -0700 Subject: [SPARC64]: Remove ktlb.S instruction patching. This was kind of ugly, and actually buggy. The bug was that we didn't handle a machine with memory starting > 4GB. If the 'prompmd' was allocated in physical memory > 4GB we'd croak because the obp_iaddr_patch and obp_daddr_patch things only supported a 32-bit physical address. So fix this by just loading the appropriate values from two variables in the kernel image, which is locked into the TLB and thus accesses to them can't cause a recursive TLB miss. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S index b717679..a591bc0 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc64/kernel/ktlb.S @@ -15,8 +15,6 @@ .text .align 32 - .globl sparc64_vpte_patchme1 - .globl sparc64_vpte_patchme2 /* * On a second level vpte miss, check whether the original fault is to the OBP * range (note that this is only possible for instruction miss, data misses to @@ -33,18 +31,17 @@ sparc64_vpte_nucleus: */ sethi %hi(LOW_OBP_ADDRESS), %g5 cmp %g4, %g5 - blu,pn %xcc, sparc64_vpte_patchme1 + blu,pn %xcc, kern_vpte mov 0x1, %g5 sllx %g5, 32, %g5 cmp %g4, %g5 - blu,pn %xcc, obp_iaddr_patch + blu,pn %xcc, vpte_insn_obp nop /* These two instructions are patched by paginig_init(). */ -sparc64_vpte_patchme1: - sethi %hi(0), %g5 -sparc64_vpte_patchme2: - or %g5, %lo(0), %g5 +kern_vpte: + sethi %hi(swapper_pgd_zero), %g5 + lduw [%g5 + %lo(swapper_pgd_zero)], %g5 /* With kernel PGD in %g5, branch back into dtlb_backend. */ ba,pt %xcc, sparc64_kpte_continue @@ -60,11 +57,9 @@ vpte_noent: stxa %g4, [%g1 + %g1] ASI_DMMU done - .globl obp_iaddr_patch -obp_iaddr_patch: - /* These two instructions patched by inherit_prom_mappings(). */ - sethi %hi(0), %g5 - or %g5, %lo(0), %g5 +vpte_insn_obp: + sethi %hi(prom_pmd_phys), %g5 + ldx [%g5 + %lo(prom_pmd_phys)], %g5 /* Behave as if we are at TL0. */ wrpr %g0, 1, %tl @@ -100,11 +95,9 @@ obp_iaddr_patch: stxa %g5, [%g0] ASI_ITLB_DATA_IN retry - .globl obp_daddr_patch -obp_daddr_patch: - /* These two instructions patched by inherit_prom_mappings(). */ - sethi %hi(0), %g5 - or %g5, %lo(0), %g5 +kvmap_do_obp: + sethi %hi(prom_pmd_phys), %g5 + ldx [%g5 + %lo(prom_pmd_phys)], %g5 /* Get PMD offset. */ srlx %g4, 23, %g6 @@ -159,7 +152,7 @@ kvmap_check_obp: mov 0x1, %g5 sllx %g5, 32, %g5 cmp %g4, %g5 - blu,pn %xcc, obp_daddr_patch + blu,pn %xcc, kvmap_do_obp nop kvmap_vmalloc_addr: diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index fdb1ebb..aaf9a3e 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -45,10 +46,10 @@ struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; unsigned long *sparc64_valid_addr_bitmap; /* Ugly, but necessary... -DaveM */ -unsigned long phys_base; -unsigned long kern_base; -unsigned long kern_size; -unsigned long pfn_base; +unsigned long phys_base __read_mostly; +unsigned long kern_base __read_mostly; +unsigned long kern_size __read_mostly; +unsigned long pfn_base __read_mostly; /* This is even uglier. We have a problem where the kernel may not be * located at phys_base. However, initial __alloc_bootmem() calls need to @@ -73,7 +74,7 @@ extern unsigned long sparc_ramdisk_image64; extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; -struct page *mem_map_zero; +struct page *mem_map_zero __read_mostly; int bigkernel = 0; @@ -318,6 +319,10 @@ extern void register_prom_callbacks(void); /* Exported for SMP bootup purposes. */ unsigned long kern_locked_tte_data; +/* Exported for kernel TLB miss handling in ktlb.S */ +unsigned long prom_pmd_phys __read_mostly; +unsigned int swapper_pgd_zero __read_mostly; + void __init early_pgtable_allocfail(char *type) { prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type); @@ -364,7 +369,6 @@ static void inherit_prom_mappings(void) pmd_t *pmdp; pte_t *ptep; int node, n, i, tsz; - extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2]; node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); @@ -434,13 +438,7 @@ static void inherit_prom_mappings(void) } } } - phys_page = __pa(prompmd); - obp_iaddr_patch[0] |= (phys_page >> 10); - obp_iaddr_patch[1] |= (phys_page & 0x3ff); - flushi((long)&obp_iaddr_patch[0]); - obp_daddr_patch[0] |= (phys_page >> 10); - obp_daddr_patch[1] |= (phys_page & 0x3ff); - flushi((long)&obp_daddr_patch[0]); + prom_pmd_phys = __pa(prompmd); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); @@ -1407,8 +1405,6 @@ static unsigned long last_valid_pfn; void __init paging_init(void) { extern pmd_t swapper_pmd_dir[1024]; - extern unsigned int sparc64_vpte_patchme1[1]; - extern unsigned int sparc64_vpte_patchme2[1]; unsigned long alias_base = kern_base + PAGE_OFFSET; unsigned long second_alias_page = 0; unsigned long pt, flags, end_pfn, pages_avail; @@ -1502,11 +1498,7 @@ void __init paging_init(void) pud_set(pud_offset(&swapper_pg_dir[0], 0), swapper_pmd_dir + (shift / sizeof(pgd_t))); - sparc64_vpte_patchme1[0] |= - (((unsigned long)pgd_val(init_mm.pgd[0])) >> 10); - sparc64_vpte_patchme2[0] |= - (((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff); - flushi((long)&sparc64_vpte_patchme1[0]); + swapper_pgd_zero = pgd_val(init_mm.pgd[0]); /* Setup bootmem... */ pages_avail = 0; -- cgit v0.10.2 From b206fc4c0997ee858bc3ed35f157d7c3cda54cfd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Sep 2005 22:31:13 -0700 Subject: [SPARC64]: Do not allocate prom translations using bootmem. Use __initdata instead. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index aaf9a3e..141d4cc5 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -310,6 +310,7 @@ struct linux_prom_translation { unsigned long size; unsigned long data; }; +static struct linux_prom_translation prom_trans[512] __initdata; extern unsigned long prom_boot_page; extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); @@ -363,7 +364,6 @@ unsigned long prom_virt_to_phys(unsigned long promva, int *error) static void inherit_prom_mappings(void) { - struct linux_prom_translation *trans; unsigned long phys_page, tte_vaddr, tte_data; void (*remap_func)(unsigned long, unsigned long, int); pmd_t *pmdp; @@ -373,30 +373,27 @@ static void inherit_prom_mappings(void) node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); if (n == 0 || n == -1) { - prom_printf("Couldn't get translation property\n"); + prom_printf("prom_mappings: Couldn't get size.\n"); prom_halt(); } - n += 5 * sizeof(struct linux_prom_translation); - for (tsz = 1; tsz < n; tsz <<= 1) - /* empty */; - trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base); - if (trans == NULL) { - prom_printf("inherit_prom_mappings: Cannot alloc translations.\n"); + n += 24 * sizeof(struct linux_prom_translation); + if (n > sizeof(prom_trans)) { + prom_printf("prom_mappings: prom_trans too small, " + "need %Zd bytes\n", n); prom_halt(); } - memset(trans, 0, tsz); - - if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { - prom_printf("Couldn't get translation property\n"); + tsz = n; + if ((n = prom_getproperty(node, "translations", + (char *)&prom_trans[0], tsz)) == -1) { + prom_printf("prom_mappings: Couldn't get property.\n"); prom_halt(); } - n = n / sizeof(*trans); + n = n / sizeof(struct linux_prom_translation); - /* - * The obp translations are saved based on 8k pagesize, since obp can - * use a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000, - * ie obp range, are handled in entry.S and do not use the vpte scheme - * (see rant in inherit_locked_prom_mappings()). + /* The obp translations are saved based on 8k pagesize, since obp + * can use a mixture of pagesizes. Misses to the 0xf0000000 -> + * 0x100000000, ie obp range, are handled in entry.S and do not + * use the vpte scheme (see rant: inherit_locked_prom_mappings). */ #define OBP_PMD_SIZE 2048 prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base); @@ -406,9 +403,9 @@ static void inherit_prom_mappings(void) for (i = 0; i < n; i++) { unsigned long vaddr; - if (trans[i].virt >= LOW_OBP_ADDRESS && trans[i].virt < HI_OBP_ADDRESS) { - for (vaddr = trans[i].virt; - ((vaddr < trans[i].virt + trans[i].size) && + if (prom_trans[i].virt >= LOW_OBP_ADDRESS && prom_trans[i].virt < HI_OBP_ADDRESS) { + for (vaddr = prom_trans[i].virt; + ((vaddr < prom_trans[i].virt + prom_trans[i].size) && (vaddr < HI_OBP_ADDRESS)); vaddr += BASE_PAGE_SIZE) { unsigned long val; @@ -426,7 +423,7 @@ static void inherit_prom_mappings(void) ptep = (pte_t *)__pmd_page(*pmdp) + ((vaddr >> 13) & 0x3ff); - val = trans[i].data; + val = prom_trans[i].data; /* Clear diag TTE bits. */ if (tlb_type == spitfire) @@ -434,7 +431,7 @@ static void inherit_prom_mappings(void) set_pte_at(&init_mm, vaddr, ptep, __pte(val | _PAGE_MODIFIED)); - trans[i].data += BASE_PAGE_SIZE; + prom_trans[i].data += BASE_PAGE_SIZE; } } } @@ -571,15 +568,16 @@ static void inherit_prom_mappings(void) } /* Re-read translations property. */ - if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) { - prom_printf("Couldn't get translation property\n"); + if ((n = prom_getproperty(node, "translations", + (char *)&prom_trans[0], tsz)) == -1) { + prom_printf("prom_mappings: Can't reread prom_trans.\n"); prom_halt(); } - n = n / sizeof(*trans); + n = n / sizeof(struct linux_prom_translation); for (i = 0; i < n; i++) { - unsigned long vaddr = trans[i].virt; - unsigned long size = trans[i].size; + unsigned long vaddr = prom_trans[i].virt; + unsigned long size = prom_trans[i].size; if (vaddr < 0xf0000000UL) { unsigned long avoid_start = (unsigned long) KERNBASE; -- cgit v0.10.2 From 1d67e6501b8dba54ef8dcabebe2ad049b8ad0d67 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:27:56 -0300 Subject: [LLC]: Make llc_frame_alloc take a net_device as an argument So as to set the newly created sk_buff ->dev member with it, that way we stop using dev_base->next, that is the wrong thing to do, as there may well be several interfaces being used with LLC. This was not such a big problem after all as most of the users of llc_alloc_frame were setting the correct dev, but this way code is reduced. This also fixes another bug in llc_station_ac_send_null_dsap_xid_c, that was not setting the skb->dev field. Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h index 353baaa..6dd4cdc 100644 --- a/include/net/llc_sap.h +++ b/include/net/llc_sap.h @@ -13,10 +13,11 @@ */ struct llc_sap; struct sk_buff; +struct net_device; extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim); -extern struct sk_buff *llc_alloc_frame(void); +extern struct sk_buff *llc_alloc_frame(struct net_device *dev); extern void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index b218be4..db98ea2 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -217,13 +217,12 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk, int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_disc_cmd(nskb, 1); @@ -243,14 +242,13 @@ free: int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit; - nskb->dev = llc->dev; llc_pdu_decode_pf_bit(skb, &f_bit); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); @@ -270,14 +268,13 @@ free: int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit = 1; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_dm_rsp(nskb, f_bit); @@ -306,11 +303,10 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) llc_pdu_decode_pf_bit(skb, &f_bit); else f_bit = 0; - nskb = llc_alloc_frame(); + nskb = llc_alloc_frame(llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, @@ -330,15 +326,14 @@ free: int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { u8 f_bit = 0; - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, @@ -360,15 +355,14 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) u8 f_bit; int rc = -ENOBUFS; struct sk_buff *nskb; + struct llc_sock *llc = llc_sk(sk); llc_pdu_decode_pf_bit(skb, &f_bit); - nskb = llc_alloc_frame(); + nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, @@ -451,13 +445,12 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, u8 nr; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); @@ -487,13 +480,12 @@ int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR); @@ -512,14 +504,13 @@ free: int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { u8 f_bit = 1; - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); @@ -538,14 +529,13 @@ free: int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit = 0; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); @@ -564,13 +554,12 @@ free: int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR); @@ -589,14 +578,13 @@ free: int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit = 1; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); @@ -615,14 +603,13 @@ free: int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { u8 f_bit = 0; - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); @@ -653,13 +640,12 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); @@ -678,13 +664,12 @@ free: int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR); @@ -703,14 +688,13 @@ free: int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit = 1; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); @@ -729,14 +713,13 @@ free: int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; u8 f_bit = 1; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); @@ -755,13 +738,12 @@ free: int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); @@ -780,13 +762,12 @@ free: int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); @@ -815,8 +796,8 @@ void llc_conn_set_p_flag(struct sock *sk, u8 value) int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -824,7 +805,6 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) if (llc->dev->flags & IFF_LOOPBACK) dmac = llc->dev->dev_addr; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_sabme_cmd(nskb, 1); @@ -845,11 +825,11 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) { u8 f_bit; int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); llc_pdu_decode_pf_bit(skb, &f_bit); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; nskb->dev = llc->dev; @@ -1001,13 +981,12 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; - struct sk_buff *nskb = llc_alloc_frame(); + struct llc_sock *llc = llc_sk(sk); + struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - nskb->dev = llc->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR); diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index ed8ba7d..270b2f2 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -103,10 +103,9 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(); + nskb = llc_alloc_frame(skb->dev); if (!nskb) goto out; - nskb->dev = skb->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, LLC_PDU_RSP); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0); @@ -149,10 +148,9 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(); + nskb = llc_alloc_frame(skb->dev); if (!nskb) goto out; - nskb->dev = skb->dev; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, LLC_PDU_RSP); llc_pdu_init_as_test_rsp(nskb, skb); diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 34228ef..0adaa28 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -26,11 +26,12 @@ /** * llc_alloc_frame - allocates sk_buff for frame + * @dev: network device this skb will be sent over * * Allocates an sk_buff for frame and initializes sk_buff fields. * Returns allocated skb or %NULL when out of memory. */ -struct sk_buff *llc_alloc_frame(void) +struct sk_buff *llc_alloc_frame(struct net_device *dev) { struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); @@ -38,7 +39,7 @@ struct sk_buff *llc_alloc_frame(void) skb_reserve(skb, 50); skb->nh.raw = skb->h.raw = skb->data; skb->protocol = htons(ETH_P_802_2); - skb->dev = dev_base->next; + skb->dev = dev; skb->mac.raw = skb->head; } return skb; diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 8fe48a2..85a7ac2 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -249,7 +249,7 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) { int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(); + struct sk_buff *nskb = llc_alloc_frame(skb->dev); if (!nskb) goto out; @@ -270,12 +270,11 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff* nskb = llc_alloc_frame(); + struct sk_buff* nskb = llc_alloc_frame(skb->dev); if (!nskb) goto out; rc = 0; - nskb->dev = skb->dev; llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_ssap(skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); @@ -295,12 +294,11 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(); + struct sk_buff *nskb = llc_alloc_frame(skb->dev); if (!nskb) goto out; rc = 0; - nskb->dev = skb->dev; llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_ssap(skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); -- cgit v0.10.2 From bdcc66cca89cc2e97e93054d139b2e9a2b2ec1a7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:38:15 -0300 Subject: [LLC]: Simplify llc_c_ac code, removing unneeded assignments to variables Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index db98ea2..309c5682 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -120,10 +120,8 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) reason = LLC_DISC_REASON_RX_DISC_CMD_PDU; } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR) reason = LLC_DISC_REASON_ACK_TMR_EXP; - else { - reason = 0; + else rc = -EINVAL; - } if (!rc) { ev->reason = reason; ev->ind_prim = LLC_DISC_PRIM; @@ -160,9 +158,6 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME) { reason = LLC_RESET_REASON_REMOTE; rc = 0; - } else { - reason = 0; - rc = 1; } break; case LLC_CONN_EV_TYPE_ACK_TMR: @@ -172,8 +167,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb) if (llc->retry_count > llc->n2) { reason = LLC_RESET_REASON_LOCAL; rc = 0; - } else - rc = 1; + } break; } if (!rc) { -- cgit v0.10.2 From 838a75dae05d59b7d7894c299508ae3d7dea9630 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:44:23 -0300 Subject: [LLC]: Remove unneeded f_bit variables Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 309c5682..9abaecc 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -267,11 +267,10 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) if (nskb) { struct llc_sap *sap = llc->sap; - u8 f_bit = 1; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_dm_rsp(nskb, f_bit); + llc_pdu_init_as_dm_rsp(nskb, 1); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; @@ -324,13 +323,12 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - u8 f_bit = 0; struct llc_sap *sap = llc->sap; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, + llc_pdu_init_as_frmr_rsp(nskb, pdu, 0, llc->vS, llc->vR, INCORRECT); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) @@ -502,12 +500,11 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - u8 f_bit = 1; struct llc_sap *sap = llc->sap; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); + llc_pdu_init_as_rej_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; @@ -528,11 +525,10 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) if (nskb) { struct llc_sap *sap = llc->sap; - u8 f_bit = 0; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR); + llc_pdu_init_as_rej_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; @@ -577,11 +573,10 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) if (nskb) { struct llc_sap *sap = llc->sap; - u8 f_bit = 1; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); + llc_pdu_init_as_rnr_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; @@ -601,12 +596,11 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) struct sk_buff *nskb = llc_alloc_frame(llc->dev); if (nskb) { - u8 f_bit = 0; struct llc_sap *sap = llc->sap; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR); + llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; @@ -712,11 +706,10 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) if (nskb) { struct llc_sap *sap = llc->sap; - u8 f_bit = 1; llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap, llc->daddr.lsap, LLC_PDU_RSP); - llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); + llc_pdu_init_as_rr_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); if (rc) goto free; -- cgit v0.10.2 From e0dd55190ff8c6485a721c9473ded92d03c0fe01 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:50:15 -0300 Subject: [LLC]: introduce llc_conn_tmr_common_cb, to avoid code duplication Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 9abaecc..50c827e 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -1326,7 +1326,7 @@ int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) return 0; } -void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) +static void llc_conn_tmr_common_cb(unsigned long timeout_data, u8 type) { struct sock *sk = (struct sock *)timeout_data; struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); @@ -1336,58 +1336,30 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) struct llc_conn_state_ev *ev = llc_conn_ev(skb); skb->sk = sk; - ev->type = LLC_CONN_EV_TYPE_P_TMR; + ev->type = type; llc_process_tmr_ev(sk, skb); } bh_unlock_sock(sk); } -void llc_conn_busy_tmr_cb(unsigned long timeout_data) +void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) { - struct sock *sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); - - bh_lock_sock(sk); - if (skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_P_TMR); +} - skb->sk = sk; - ev->type = LLC_CONN_EV_TYPE_BUSY_TMR; - llc_process_tmr_ev(sk, skb); - } - bh_unlock_sock(sk); +void llc_conn_busy_tmr_cb(unsigned long timeout_data) +{ + llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_BUSY_TMR); } void llc_conn_ack_tmr_cb(unsigned long timeout_data) { - struct sock* sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); - - bh_lock_sock(sk); - if (skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); - - skb->sk = sk; - ev->type = LLC_CONN_EV_TYPE_ACK_TMR; - llc_process_tmr_ev(sk, skb); - } - bh_unlock_sock(sk); + llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_ACK_TMR); } void llc_conn_rej_tmr_cb(unsigned long timeout_data) { - struct sock *sk = (struct sock *)timeout_data; - struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); - - bh_lock_sock(sk); - if (skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); - - skb->sk = sk; - ev->type = LLC_CONN_EV_TYPE_REJ_TMR; - llc_process_tmr_ev(sk, skb); - } - bh_unlock_sock(sk); + llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_REJ_TMR); } int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb) -- cgit v0.10.2 From 774ccb4f64020dad40d38efa63685220e1f245cc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:53:35 -0300 Subject: [LLC]: Remove unneeded temp net_device variables Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 66f55e5..2975d88 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -404,7 +404,6 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr; - struct net_device *dev; int rc = -EINVAL; lock_sock(sk); @@ -422,7 +421,6 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, llc->daddr.lsap = addr->sllc_sap; memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN); } - dev = llc->dev; if (sk->sk_type != SOCK_STREAM) goto out; rc = -EALREADY; @@ -431,7 +429,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTING; sk->sk_state = TCP_SYN_SENT; llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); - rc = llc_establish_connection(sk, dev->dev_addr, + rc = llc_establish_connection(sk, llc->dev->dev_addr, addr->sllc_mac, addr->sllc_sap); if (rc) { dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__); @@ -740,7 +738,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name; int flags = msg->msg_flags; int noblock = flags & MSG_DONTWAIT; - struct net_device *dev; struct sk_buff *skb; size_t size = 0; int rc = -EINVAL, copied = 0, hdrlen; @@ -763,11 +760,10 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, if (rc) goto release; } - dev = llc->dev; - hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr); + hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr); size = hdrlen + len; - if (size > dev->mtu) - size = dev->mtu; + if (size > llc->dev->mtu) + size = llc->dev->mtu; copied = size - hdrlen; release_sock(sk); skb = sock_alloc_send_skb(sk, size, noblock, &rc); @@ -775,7 +771,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, if (!skb) goto release; skb->sk = sk; - skb->dev = dev; + skb->dev = llc->dev; skb->protocol = llc_proto_type(addr->sllc_arphrd); skb_reserve(skb, hdrlen); rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied); -- cgit v0.10.2 From 5a770c0262262e96979fe05d5c2fa1d1f409dbdc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:56:26 -0300 Subject: [LLC]: Update comments for llc_ui_bind and llc_ui_autobind to match new behaviour Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2975d88..81a5379 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -231,20 +231,13 @@ out: } /** - * llc_ui_autobind - Bind a socket to a specific address. - * @sk: Socket to bind an address to. - * @addr: Address the user wants the socket bound to. + * llc_ui_autobind - automatically bind a socket to a sap + * @sock: socket to bind + * @addr: address to connect to + * + * Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't + * specifically used llc_ui_bind to bind to an specific address/sap * - * Bind a socket to a specific address. For llc a user is able to bind to - * a specific sap only or mac + sap. If the user only specifies a sap and - * a null dmac (all zeros) the user is attempting to bind to an entire - * sap. This will stop anyone else on the local system from using that - * sap. If someone else has a mac + sap open the bind to null + sap will - * fail. - * If the user desires to bind to a specific mac + sap, it is possible to - * have multiple sap connections via multiple macs. - * Bind and autobind for that matter must enforce the correct sap usage - * otherwise all hell will break loose. * Returns: 0 upon success, negative otherwise. */ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) @@ -285,11 +278,7 @@ out: * @addrlen: Length of the uaddr structure. * * Bind a socket to a specific address. For llc a user is able to bind to - * a specific sap only or mac + sap. If the user only specifies a sap and - * a null dmac (all zeros) the user is attempting to bind to an entire - * sap. This will stop anyone else on the local system from using that - * sap. If someone else has a mac + sap open the bind to null + sap will - * fail. + * a specific sap only or mac + sap. * If the user desires to bind to a specific mac + sap, it is possible to * have multiple sap connections via multiple macs. * Bind and autobind for that matter must enforce the correct sap usage -- cgit v0.10.2 From 0eb8017242cb7e8b18af4751b03646436b8f90e3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:57:55 -0300 Subject: [LLC]: Mark llc_find_next_offset as __init, saving some more bytes Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 4c644bc..1f659e5 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -544,14 +544,14 @@ u8 llc_data_accept_state(u8 state) } /** - * find_next_offset - finds offset for next category of transitions + * llc_find_next_offset - finds offset for next category of transitions * @state: state table. * @offset: start offset. * * Finds offset of next category of transitions in transition table. * Returns the start index of next category. */ -static u16 find_next_offset(struct llc_conn_state *state, u16 offset) +static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset) { u16 cnt = 0; struct llc_conn_state_trans **next_trans; @@ -578,8 +578,8 @@ void __init llc_build_offset_table(void) next_offset = 0; for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) { llc_offset_table[state][ev_type] = next_offset; - next_offset += find_next_offset(curr_state, - next_offset) + 1; + next_offset += llc_find_next_offset(curr_state, + next_offset) + 1; } } } -- cgit v0.10.2 From af426d327c38bcb8cbb87c60134d42d2e93b20cc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 03:59:22 -0300 Subject: [LLC]: Help the compiler with likely/unlikely, saving some more bytes Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 81a5379..aed61e6 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -155,7 +155,7 @@ static int llc_ui_create(struct socket *sock, int protocol) struct sock *sk; int rc = -ESOCKTNOSUPPORT; - if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) { + if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) { rc = -ENOMEM; sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto); if (sk) { @@ -177,7 +177,7 @@ static int llc_ui_release(struct socket *sock) struct sock *sk = sock->sk; struct llc_sock *llc; - if (!sk) + if (unlikely(sk == NULL)) goto out; sock_hold(sk); lock_sock(sk); @@ -294,10 +294,10 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) int rc = -EINVAL; dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap); - if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)) + if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))) goto out; rc = -EAFNOSUPPORT; - if (addr->sllc_family != AF_LLC) + if (unlikely(addr->sllc_family != AF_LLC)) goto out; if (!addr->sllc_sap) { rc = -EUSERS; @@ -358,7 +358,7 @@ static int llc_ui_shutdown(struct socket *sock, int how) int rc = -ENOTCONN; lock_sock(sk); - if (sk->sk_state != TCP_ESTABLISHED) + if (unlikely(sk->sk_state != TCP_ESTABLISHED)) goto out; rc = -EINVAL; if (how != 2) @@ -396,10 +396,15 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, int rc = -EINVAL; lock_sock(sk); - if (addrlen != sizeof(*addr)) + if (unlikely(addrlen != sizeof(*addr))) goto out; rc = -EAFNOSUPPORT; - if (addr->sllc_family != AF_LLC) + if (unlikely(addr->sllc_family != AF_LLC)) + goto out; + if (unlikely(sk->sk_type != SOCK_STREAM)) + goto out; + rc = -EALREADY; + if (unlikely(sock->state == SS_CONNECTING)) goto out; /* bind connection to sap if user hasn't done it. */ if (sock_flag(sk, SOCK_ZAPPED)) { @@ -410,11 +415,6 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, llc->daddr.lsap = addr->sllc_sap; memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN); } - if (sk->sk_type != SOCK_STREAM) - goto out; - rc = -EALREADY; - if (sock->state == SS_CONNECTING) - goto out; sock->state = SS_CONNECTING; sk->sk_state = TCP_SYN_SENT; llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); @@ -448,10 +448,10 @@ static int llc_ui_listen(struct socket *sock, int backlog) int rc = -EINVAL; lock_sock(sk); - if (sock->state != SS_UNCONNECTED) + if (unlikely(sock->state != SS_UNCONNECTED)) goto out; rc = -EOPNOTSUPP; - if (sk->sk_type != SOCK_STREAM) + if (unlikely(sk->sk_type != SOCK_STREAM)) goto out; rc = -EAGAIN; if (sock_flag(sk, SOCK_ZAPPED)) @@ -614,10 +614,11 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) dprintk("%s: accepting on %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap); lock_sock(sk); - if (sk->sk_type != SOCK_STREAM) + if (unlikely(sk->sk_type != SOCK_STREAM)) goto out; rc = -EINVAL; - if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN) + if (unlikely(sock->state != SS_UNCONNECTED || + sk->sk_state != TCP_LISTEN)) goto out; /* wait for a connection to arrive. */ rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); @@ -880,7 +881,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, int rc = -EINVAL, opt; lock_sock(sk); - if (level != SOL_LLC || optlen != sizeof(int)) + if (unlikely(level != SOL_LLC || optlen != sizeof(int))) goto out; rc = get_user(opt, (int __user *)optval); if (rc) @@ -955,7 +956,7 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, int val = 0, len = 0, rc = -EINVAL; lock_sock(sk); - if (level != SOL_LLC) + if (unlikely(level != SOL_LLC)) goto out; rc = get_user(len, optlen); if (rc) diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 1f659e5..ce7b893 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -64,12 +64,12 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) skb_get(skb); ev->ind_prim = ev->cfm_prim = 0; rc = llc_conn_service(sk, skb); /* sending event to state machine */ - if (rc) { + if (unlikely(rc != 0)) { printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__); goto out_kfree_skb; } - if (!ev->ind_prim && !ev->cfm_prim) { + if (unlikely(!ev->ind_prim && !ev->cfm_prim)) { /* indicate or confirm not required */ /* XXX this is not very pretty, perhaps we should store * XXX indicate/confirm-needed state in the llc_conn_state_ev @@ -80,7 +80,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) goto out_skb_put; } - if (ev->ind_prim && ev->cfm_prim) /* Paranoia */ + if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */ skb_get(skb); switch (ev->ind_prim) { @@ -762,14 +762,14 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) int rc = 0; struct llc_sock *llc = llc_sk(sk); - if (llc_backlog_type(skb) == LLC_PACKET) { - if (llc->state > 1) /* not closed */ + if (likely(llc_backlog_type(skb) == LLC_PACKET)) { + if (likely(llc->state > 1)) /* not closed */ rc = llc_conn_rcv(sk, skb); else goto out_kfree_skb; } else if (llc_backlog_type(skb) == LLC_EVENT) { /* timer expiration event */ - if (llc->state > 1) /* not closed */ + if (likely(llc->state > 1)) /* not closed */ rc = llc_conn_state_process(sk, skb); else goto out_kfree_skb; diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 13b4624..60c1aca 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -101,7 +101,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb) u8 llc_len = 2; struct llc_pdu_sn *pdu; - if (!pskb_may_pull(skb, sizeof(*pdu))) + if (unlikely(!pskb_may_pull(skb, sizeof(*pdu)))) return 0; pdu = (struct llc_pdu_sn *)skb->data; -- cgit v0.10.2 From b9441fc3375a6637a81bc1635c5e12da4dc7acc6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:09:45 -0300 Subject: [LLC]: Use const in llc_c_ev.c Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c index d5bdb53..c53b823 100644 --- a/net/llc/llc_c_ev.c +++ b/net/llc/llc_c_ev.c @@ -99,7 +99,7 @@ out: int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->prim == LLC_CONN_PRIM && ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; @@ -107,7 +107,7 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->prim == LLC_DATA_PRIM && ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; @@ -115,7 +115,7 @@ int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->prim == LLC_DISC_PRIM && ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; @@ -123,7 +123,7 @@ int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->prim == LLC_RESET_PRIM && ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; @@ -131,7 +131,7 @@ int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type == LLC_CONN_EV_TYPE_SIMPLE && ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1; @@ -139,7 +139,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type == LLC_CONN_EV_TYPE_SIMPLE && ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1; @@ -152,7 +152,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1; @@ -160,7 +160,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1; @@ -168,7 +168,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1; @@ -176,7 +176,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && @@ -186,7 +186,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && @@ -197,9 +197,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_I_PF_IS_0(pdu) && ns != vr && @@ -209,9 +209,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_I_PF_IS_1(pdu) && ns != vr && @@ -221,10 +221,11 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); - u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && + const struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); + const u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && + ns != vr && llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; if (!rc) dprintk("%s: matched, state=%d, ns=%d, vr=%d\n", @@ -234,7 +235,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && @@ -244,7 +245,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_I_PF_IS_1(pdu) && @@ -253,7 +254,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && @@ -263,9 +264,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_I_PF_IS_0(pdu) && ns != vr && @@ -275,9 +276,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && LLC_I_PF_IS_1(pdu) && ns != vr && @@ -287,9 +288,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; @@ -298,10 +299,11 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk, int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vr = llc_sk(sk)->vR; - u8 ns = LLC_I_GET_NS(pdu); - u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr && + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vr = llc_sk(sk)->vR; + const u8 ns = LLC_I_GET_NS(pdu); + const u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && + ns != vr && llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; if (!rc) dprintk("%s: matched, state=%d, ns=%d, vr=%d\n", @@ -311,7 +313,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_0(pdu) && @@ -320,7 +322,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_1(pdu) && @@ -329,7 +331,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_0(pdu) && @@ -338,7 +340,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_1(pdu) && @@ -347,7 +349,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1; @@ -355,7 +357,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_0(pdu) && @@ -364,7 +366,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_1(pdu) && @@ -373,7 +375,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_0(pdu) && @@ -382,7 +384,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_1(pdu) && @@ -391,7 +393,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_0(pdu) && @@ -400,7 +402,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) && LLC_S_PF_IS_1(pdu) && @@ -409,7 +411,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && @@ -419,7 +421,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); return llc_conn_space(sk, skb) && LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) && @@ -429,7 +431,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) { - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1; @@ -446,7 +448,7 @@ int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); if (LLC_PDU_IS_CMD(pdu)) { if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) { @@ -461,7 +463,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); if (LLC_PDU_IS_CMD(pdu)) { if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) @@ -480,7 +482,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); if (LLC_PDU_IS_RSP(pdu)) { if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) { @@ -502,7 +504,7 @@ int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); + const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); if (LLC_PDU_IS_RSP(pdu)) { if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) @@ -524,9 +526,9 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vs = llc_sk(sk)->vS; - u8 nr = LLC_I_GET_NR(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vs = llc_sk(sk)->vS; + const u8 nr = LLC_I_GET_NR(pdu); if (LLC_PDU_IS_CMD(pdu) && (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) && @@ -542,9 +544,9 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; - struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - u8 vs = llc_sk(sk)->vS; - u8 nr = LLC_I_GET_NR(pdu); + const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + const u8 vs = llc_sk(sk)->vS; + const u8 nr = LLC_I_GET_NR(pdu); if (LLC_PDU_IS_RSP(pdu) && (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) && @@ -563,28 +565,28 @@ int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type != LLC_CONN_EV_TYPE_P_TMR; } int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type != LLC_CONN_EV_TYPE_ACK_TMR; } int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type != LLC_CONN_EV_TYPE_REJ_TMR; } int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR; } @@ -596,7 +598,7 @@ int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb) int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); + const struct llc_conn_state_ev *ev = llc_conn_ev(skb); return ev->type == LLC_CONN_EV_TYPE_SIMPLE && ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1; -- cgit v0.10.2 From 405599bd98b01d648becb020efb503abf19f9c9f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 00:12:35 -0700 Subject: [SPARC64]: Break up inherit_prom_mappings() into it's constituent parts. This thing was just a huge monolithic mess, so chop it up. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 141d4cc5..11d2187 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -362,84 +362,107 @@ unsigned long prom_virt_to_phys(unsigned long promva, int *error) return(base + (promva & (BASE_PAGE_SIZE - 1))); } -static void inherit_prom_mappings(void) +static inline int in_obp_range(unsigned long vaddr) { - unsigned long phys_page, tte_vaddr, tte_data; - void (*remap_func)(unsigned long, unsigned long, int); - pmd_t *pmdp; - pte_t *ptep; - int node, n, i, tsz; + return (vaddr >= LOW_OBP_ADDRESS && + vaddr < HI_OBP_ADDRESS); +} - node = prom_finddevice("/virtual-memory"); - n = prom_getproplen(node, "translations"); - if (n == 0 || n == -1) { - prom_printf("prom_mappings: Couldn't get size.\n"); - prom_halt(); - } - n += 24 * sizeof(struct linux_prom_translation); - if (n > sizeof(prom_trans)) { - prom_printf("prom_mappings: prom_trans too small, " - "need %Zd bytes\n", n); - prom_halt(); - } - tsz = n; - if ((n = prom_getproperty(node, "translations", - (char *)&prom_trans[0], tsz)) == -1) { - prom_printf("prom_mappings: Couldn't get property.\n"); - prom_halt(); +/* The obp translations are saved based on 8k pagesize, since obp can + * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS -> + * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte + * scheme (also, see rant in inherit_locked_prom_mappings()). + */ +static void build_obp_range(unsigned long start, unsigned long end, unsigned long data) +{ + unsigned long vaddr; + + for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { + unsigned long val; + pmd_t *pmdp; + pte_t *ptep; + + pmdp = prompmd + ((vaddr >> 23) & 0x7ff); + if (pmd_none(*pmdp)) { + ptep = __alloc_bootmem(BASE_PAGE_SIZE, + BASE_PAGE_SIZE, + bootmap_base); + if (ptep == NULL) + early_pgtable_allocfail("pte"); + memset(ptep, 0, BASE_PAGE_SIZE); + pmd_set(pmdp, ptep); + } + ptep = (pte_t *)__pmd_page(*pmdp) + + ((vaddr >> 13) & 0x3ff); + + val = data; + + /* Clear diag TTE bits. */ + if (tlb_type == spitfire) + val &= ~0x0003fe0000000000UL; + + set_pte_at(&init_mm, vaddr, + ptep, __pte(val | _PAGE_MODIFIED)); + data += BASE_PAGE_SIZE; } - n = n / sizeof(struct linux_prom_translation); +} - /* The obp translations are saved based on 8k pagesize, since obp - * can use a mixture of pagesizes. Misses to the 0xf0000000 -> - * 0x100000000, ie obp range, are handled in entry.S and do not - * use the vpte scheme (see rant: inherit_locked_prom_mappings). - */ #define OBP_PMD_SIZE 2048 - prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base); +static void build_obp_pgtable(int prom_trans_ents) +{ + int i; + + prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, + bootmap_base); if (prompmd == NULL) early_pgtable_allocfail("pmd"); memset(prompmd, 0, OBP_PMD_SIZE); - for (i = 0; i < n; i++) { - unsigned long vaddr; - - if (prom_trans[i].virt >= LOW_OBP_ADDRESS && prom_trans[i].virt < HI_OBP_ADDRESS) { - for (vaddr = prom_trans[i].virt; - ((vaddr < prom_trans[i].virt + prom_trans[i].size) && - (vaddr < HI_OBP_ADDRESS)); - vaddr += BASE_PAGE_SIZE) { - unsigned long val; - - pmdp = prompmd + ((vaddr >> 23) & 0x7ff); - if (pmd_none(*pmdp)) { - ptep = __alloc_bootmem(BASE_PAGE_SIZE, - BASE_PAGE_SIZE, - bootmap_base); - if (ptep == NULL) - early_pgtable_allocfail("pte"); - memset(ptep, 0, BASE_PAGE_SIZE); - pmd_set(pmdp, ptep); - } - ptep = (pte_t *)__pmd_page(*pmdp) + - ((vaddr >> 13) & 0x3ff); + for (i = 0; i < prom_trans_ents; i++) { + unsigned long start, end; - val = prom_trans[i].data; + if (!in_obp_range(prom_trans[i].virt)) + continue; - /* Clear diag TTE bits. */ - if (tlb_type == spitfire) - val &= ~0x0003fe0000000000UL; + start = prom_trans[i].virt; + end = start + prom_trans[i].size; + if (end > HI_OBP_ADDRESS) + end = HI_OBP_ADDRESS; - set_pte_at(&init_mm, vaddr, - ptep, __pte(val | _PAGE_MODIFIED)); - prom_trans[i].data += BASE_PAGE_SIZE; - } - } + build_obp_range(start, end, prom_trans[i].data); } prom_pmd_phys = __pa(prompmd); +} - /* Now fixup OBP's idea about where we really are mapped. */ - prom_printf("Remapping the kernel... "); +/* Read OBP translations property into 'prom_trans[]'. + * Return the number of entries. + */ +static int read_obp_translations(void) +{ + int n, node; + node = prom_finddevice("/virtual-memory"); + n = prom_getproplen(node, "translations"); + if (unlikely(n == 0 || n == -1)) { + prom_printf("prom_mappings: Couldn't get size.\n"); + prom_halt(); + } + if (unlikely(n > sizeof(prom_trans))) { + prom_printf("prom_mappings: Size %Zd is too big.\n", n); + prom_halt(); + } + + if ((n = prom_getproperty(node, "translations", + (char *)&prom_trans[0], + sizeof(prom_trans))) == -1) { + prom_printf("prom_mappings: Couldn't get property.\n"); + prom_halt(); + } + n = n / sizeof(struct linux_prom_translation); + return n; +} + +static inline void early_spitfire_errata32(void) +{ /* Spitfire Errata #32 workaround */ /* NOTE: Using plain zero for the context value is * correct here, we are not using the Linux trap @@ -449,23 +472,13 @@ static void inherit_prom_mappings(void) __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ - : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - switch (tlb_type) { - default: - case spitfire: - phys_page = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()); - break; - - case cheetah: - case cheetah_plus: - phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); - break; - }; + : "r" (0), "r" (PRIMARY_CONTEXT), + "i" (ASI_DMMU)); +} - phys_page &= _PAGE_PADDR; - phys_page += ((unsigned long)&prom_boot_page - - (unsigned long)KERNBASE); +static void lock_remap_func_page(unsigned long phys_page) +{ + unsigned long tte_data = (phys_page | pgprot_val(PAGE_KERNEL)); if (tlb_type == spitfire) { /* Lock this into i/d tlb entry 59 */ @@ -478,13 +491,12 @@ static void inherit_prom_mappings(void) "stxa %0, [%1] %6\n\t" "membar #Sync\n\t" "flush %%g6" - : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP | - _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), - "r" (59 << 3), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), - "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) - : "memory"); - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { + : /* no outputs */ + : "r" (tte_data), "r" (59 << 3), "r" (TLB_TAG_ACCESS), + "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), + "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) + : "memory"); + } else { /* Lock this into i/d tlb-0 entry 11 */ __asm__ __volatile__( "stxa %%g0, [%2] %3\n\t" @@ -495,87 +507,80 @@ static void inherit_prom_mappings(void) "stxa %0, [%1] %6\n\t" "membar #Sync\n\t" "flush %%g6" - : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP | - _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W), - "r" ((0 << 16) | (11 << 3)), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), - "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) + : /* no outputs */ + : "r" (tte_data), "r" ((0 << 16) | (11 << 3)), + "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU), + "i" (ASI_DTLB_DATA_ACCESS), "i" (ASI_IMMU), + "i" (ASI_ITLB_DATA_ACCESS) : "memory"); - } else { - /* Implement me :-) */ - BUG(); } +} + +static void remap_kernel(void) +{ + unsigned long phys_page, tte_vaddr, tte_data; + void (*remap_func)(unsigned long, unsigned long, int); + int tlb_ent = sparc64_highest_locked_tlbent(); + + early_spitfire_errata32(); + + if (tlb_type == spitfire) + phys_page = spitfire_get_dtlb_data(tlb_ent); + else + phys_page = cheetah_get_ldtlb_data(tlb_ent); + + phys_page &= _PAGE_PADDR; + phys_page += ((unsigned long)&prom_boot_page - + (unsigned long)KERNBASE); + + lock_remap_func_page(phys_page); tte_vaddr = (unsigned long) KERNBASE; - /* Spitfire Errata #32 workaround */ - /* NOTE: Using plain zero for the context value is - * correct here, we are not using the Linux trap - * tables yet so we should not use the special - * UltraSPARC-III+ page size encodings yet. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + early_spitfire_errata32(); if (tlb_type == spitfire) - tte_data = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()); + tte_data = spitfire_get_dtlb_data(tlb_ent); else - tte_data = cheetah_get_ldtlb_data(sparc64_highest_locked_tlbent()); + tte_data = cheetah_get_ldtlb_data(tlb_ent); kern_locked_tte_data = tte_data; remap_func = (void *) ((unsigned long) &prom_remap - (unsigned long) &prom_boot_page); + early_spitfire_errata32(); - /* Spitfire Errata #32 workaround */ - /* NOTE: Using plain zero for the context value is - * correct here, we are not using the Linux trap - * tables yet so we should not use the special - * UltraSPARC-III+ page size encodings yet. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), - "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); - - remap_func((tlb_type == spitfire ? - (spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR) : - (cheetah_get_litlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR)), - (unsigned long) KERNBASE, - prom_get_mmu_ihandle()); - + phys_page = tte_data & _PAGE_PADDR; + remap_func(phys_page, KERNBASE, prom_get_mmu_ihandle()); if (bigkernel) - remap_func(((tte_data + 0x400000) & _PAGE_PADDR), - (unsigned long) KERNBASE + 0x400000, prom_get_mmu_ihandle()); + remap_func(phys_page + 0x400000, + KERNBASE + 0x400000, + prom_get_mmu_ihandle()); /* Flush out that temporary mapping. */ spitfire_flush_dtlb_nucleus_page(0x0); spitfire_flush_itlb_nucleus_page(0x0); /* Now lock us back into the TLBs via OBP. */ - prom_dtlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr); - prom_itlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr); + prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); + prom_itlb_load(tlb_ent, tte_data, tte_vaddr); if (bigkernel) { - prom_dtlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, - tte_vaddr + 0x400000); - prom_itlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, - tte_vaddr + 0x400000); + prom_dtlb_load(tlb_ent - 1, + tte_data + 0x400000, + tte_vaddr + 0x400000); + prom_itlb_load(tlb_ent - 1, + tte_data + 0x400000, + tte_vaddr + 0x400000); } +} - /* Re-read translations property. */ - if ((n = prom_getproperty(node, "translations", - (char *)&prom_trans[0], tsz)) == -1) { - prom_printf("prom_mappings: Can't reread prom_trans.\n"); - prom_halt(); - } - n = n / sizeof(struct linux_prom_translation); +static void readjust_prom_translations(void) +{ + int nents, i; - for (i = 0; i < n; i++) { + nents = read_obp_translations(); + for (i = 0; i < nents; i++) { unsigned long vaddr = prom_trans[i].virt; unsigned long size = prom_trans[i].size; @@ -601,6 +606,20 @@ static void inherit_prom_mappings(void) } } } +} + +static void inherit_prom_mappings(void) +{ + int n; + + n = read_obp_translations(); + build_obp_pgtable(n); + + /* Now fixup OBP's idea about where we really are mapped. */ + prom_printf("Remapping the kernel... "); + remap_kernel(); + + readjust_prom_translations(); prom_printf("done.\n"); -- cgit v0.10.2 From 72b1ad4a7e239a2224e87194654acba56fc477d4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:19:52 -0300 Subject: [LLC]: Remove unused functions from llc_c_ev.c Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c index c53b823..c5deda2 100644 --- a/net/llc/llc_c_ev.c +++ b/net/llc/llc_c_ev.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -46,8 +47,6 @@ #define dprintk(args...) #endif -extern u16 llc_circular_between(u8 a, u8 b, u8 c); - /** * llc_util_ns_inside_rx_window - check if sequence number is in rx window * @ns: sequence number of received pdu. @@ -479,28 +478,6 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb) return rc; } -int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb) -{ - u16 rc = 1; - const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); - - if (LLC_PDU_IS_RSP(pdu)) { - if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) { - if (LLC_I_PF_IS_1(pdu)) - rc = 0; - } else if (LLC_PDU_TYPE_IS_U(pdu)) - switch (LLC_U_PDU_RSP(pdu)) { - case LLC_2_PDU_RSP_UA: - case LLC_2_PDU_RSP_DM: - case LLC_2_PDU_RSP_FRMR: - if (LLC_U_PF_IS_1(pdu)) - rc = 0; - break; - } - } - return rc; -} - int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb) { u16 rc = 1; -- cgit v0.10.2 From b35bd11019ed1084a36632f1c1d936244d9cfb5b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:22:39 -0300 Subject: [LLC]: Convert llc_ui_wait_for_ functions to use prepare_to_wait/finish_wait And make it look more like the similar routines in the TCP/IP source code. Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index aed61e6..436c8db 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -426,12 +426,30 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, sk->sk_state = TCP_CLOSE; goto out; } - rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo); - if (rc) - dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc); + + if (sk->sk_state == TCP_SYN_SENT) { + const int timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + + if (!timeo || !llc_ui_wait_for_conn(sk, timeo)) + goto out; + + rc = sock_intr_errno(timeo); + if (signal_pending(current)) + goto out; + } + + if (sk->sk_state == TCP_CLOSE) + goto sock_error; + + sock->state = SS_CONNECTED; + rc = 0; out: release_sock(sk); return rc; +sock_error: + rc = sock_error(sk) ? : -ECONNABORTED; + sock->state = SS_UNCONNECTED; + goto out; } /** @@ -472,117 +490,88 @@ out: static int llc_ui_wait_for_disc(struct sock *sk, int timeout) { - DECLARE_WAITQUEUE(wait, current); - int rc; + DEFINE_WAIT(wait); + int rc = 0; - add_wait_queue_exclusive(sk->sk_sleep, &wait); - for (;;) { - __set_current_state(TASK_INTERRUPTIBLE); - rc = 0; - if (sk->sk_state != TCP_CLOSE) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } else - break; + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + while (sk->sk_state != TCP_CLOSE) { + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); rc = -ERESTARTSYS; if (signal_pending(current)) break; rc = -EAGAIN; if (!timeout) break; + rc = 0; + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); } - __set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); + finish_wait(sk->sk_sleep, &wait); return rc; } static int llc_ui_wait_for_conn(struct sock *sk, int timeout) { - DECLARE_WAITQUEUE(wait, current); - int rc; + DEFINE_WAIT(wait); - add_wait_queue_exclusive(sk->sk_sleep, &wait); - for (;;) { - __set_current_state(TASK_INTERRUPTIBLE); - rc = -EAGAIN; - if (sk->sk_state == TCP_CLOSE) - break; - rc = 0; - if (sk->sk_state != TCP_ESTABLISHED) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } else - break; - rc = -ERESTARTSYS; - if (signal_pending(current)) - break; - rc = -EAGAIN; - if (!timeout) + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + + while (sk->sk_state == TCP_SYN_SENT) { + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + if (signal_pending(current) || !timeout) break; + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); } - __set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); - return rc; + finish_wait(sk->sk_sleep, &wait); + return timeout; } static int llc_ui_wait_for_data(struct sock *sk, int timeout) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); int rc = 0; - add_wait_queue_exclusive(sk->sk_sleep, &wait); for (;;) { - __set_current_state(TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); if (sk->sk_shutdown & RCV_SHUTDOWN) break; - /* - * Well, if we have backlog, try to process it now. - */ - if (sk->sk_backlog.tail) { - release_sock(sk); - lock_sock(sk); - } - rc = 0; - if (skb_queue_empty(&sk->sk_receive_queue)) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } else + if (!skb_queue_empty(&sk->sk_receive_queue)) break; + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); rc = -ERESTARTSYS; if (signal_pending(current)) break; rc = -EAGAIN; if (!timeout) break; + rc = 0; } - __set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); + finish_wait(sk->sk_sleep, &wait); return rc; } static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct llc_sock *llc = llc_sk(sk); int rc; - add_wait_queue_exclusive(sk->sk_sleep, &wait); for (;;) { - dprintk("%s: looping...\n", __FUNCTION__); - __set_current_state(TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); rc = -ENOTCONN; if (sk->sk_shutdown & RCV_SHUTDOWN) break; rc = 0; - if (llc_data_accept_state(llc->state) || llc->p_flag) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); - } else + if (!llc_data_accept_state(llc->state) && !llc->p_flag) break; + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); rc = -ERESTARTSYS; if (signal_pending(current)) break; @@ -590,8 +579,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) if (!timeout) break; } - __set_current_state(TASK_RUNNING); - remove_wait_queue(sk->sk_sleep, &wait); + finish_wait(sk->sk_sleep, &wait); return rc; } @@ -621,9 +609,11 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) sk->sk_state != TCP_LISTEN)) goto out; /* wait for a connection to arrive. */ - rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); - if (rc) - goto out; + if (skb_queue_empty(&sk->sk_receive_queue)) { + rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); + if (rc) + goto out; + } dprintk("%s: got a new connection on %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap); skb = skb_dequeue(&sk->sk_receive_queue); @@ -672,19 +662,16 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; struct sk_buff *skb; size_t copied = 0; - int rc = -ENOMEM, timeout; + int rc = -ENOMEM; int noblock = flags & MSG_DONTWAIT; dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__, llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); lock_sock(sk); - timeout = sock_rcvtimeo(sk, noblock); - rc = llc_ui_wait_for_data(sk, timeout); - if (rc) { - dprintk("%s: llc_ui_wait_for_data failed recv " - "in %02X from %02X\n", __FUNCTION__, - llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); - goto out; + if (skb_queue_empty(&sk->sk_receive_queue)) { + rc = llc_ui_wait_for_data(sk, sock_rcvtimeo(sk, noblock)); + if (rc) + goto out; } skb = skb_dequeue(&sk->sk_receive_queue); if (!skb) /* shutdown */ -- cgit v0.10.2 From 54fb7f25f19a4539d3ec012e410439913650dc06 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:26:14 -0300 Subject: [LLC]: Use the sk_wait_event primitive Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 436c8db..95444f2 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -37,10 +37,10 @@ static u16 llc_ui_sap_link_no_max[256]; static struct sockaddr_llc llc_ui_addrnull; static struct proto_ops llc_ui_ops; -static int llc_ui_wait_for_conn(struct sock *sk, int timeout); -static int llc_ui_wait_for_disc(struct sock *sk, int timeout); -static int llc_ui_wait_for_data(struct sock *sk, int timeout); -static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout); +static int llc_ui_wait_for_conn(struct sock *sk, long timeout); +static int llc_ui_wait_for_disc(struct sock *sk, long timeout); +static int llc_ui_wait_for_data(struct sock *sk, long timeout); +static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout); #if 0 #define dprintk(args...) printk(KERN_DEBUG args) @@ -117,7 +117,7 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) int rc = 0; if (llc_data_accept_state(llc->state) || llc->p_flag) { - int timeout = sock_sndtimeo(sk, noblock); + long timeout = sock_sndtimeo(sk, noblock); rc = llc_ui_wait_for_busy_core(sk, timeout); } @@ -428,7 +428,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, } if (sk->sk_state == TCP_SYN_SENT) { - const int timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); + const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); if (!timeo || !llc_ui_wait_for_conn(sk, timeo)) goto out; @@ -488,16 +488,15 @@ out: return rc; } -static int llc_ui_wait_for_disc(struct sock *sk, int timeout) +static int llc_ui_wait_for_disc(struct sock *sk, long timeout) { DEFINE_WAIT(wait); int rc = 0; - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - while (sk->sk_state != TCP_CLOSE) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); + while (1) { + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE)) + break; rc = -ERESTARTSYS; if (signal_pending(current)) break; @@ -505,44 +504,37 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout) if (!timeout) break; rc = 0; - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); return rc; } -static int llc_ui_wait_for_conn(struct sock *sk, int timeout) +static int llc_ui_wait_for_conn(struct sock *sk, long timeout) { DEFINE_WAIT(wait); - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - - while (sk->sk_state == TCP_SYN_SENT) { - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); + while (1) { + prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT)) + break; if (signal_pending(current) || !timeout) break; - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); return timeout; } -static int llc_ui_wait_for_data(struct sock *sk, int timeout) +static int llc_ui_wait_for_data(struct sock *sk, long timeout) { DEFINE_WAIT(wait); int rc = 0; - for (;;) { + while (1) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - if (sk->sk_shutdown & RCV_SHUTDOWN) - break; - if (!skb_queue_empty(&sk->sk_receive_queue)) + if (sk_wait_event(sk, &timeout, + (sk->sk_shutdown & RCV_SHUTDOWN) || + (!skb_queue_empty(&sk->sk_receive_queue)))) break; - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); rc = -ERESTARTSYS; if (signal_pending(current)) break; @@ -555,23 +547,20 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout) return rc; } -static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) +static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) { DEFINE_WAIT(wait); struct llc_sock *llc = llc_sk(sk); int rc; - for (;;) { + while (1) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - rc = -ENOTCONN; - if (sk->sk_shutdown & RCV_SHUTDOWN) - break; rc = 0; - if (!llc_data_accept_state(llc->state) && !llc->p_flag) + if (sk_wait_event(sk, &timeout, + (sk->sk_shutdown & RCV_SHUTDOWN) || + (!llc_data_accept_state(llc->state) && + !llc->p_flag))) break; - release_sock(sk); - timeout = schedule_timeout(timeout); - lock_sock(sk); rc = -ERESTARTSYS; if (signal_pending(current)) break; -- cgit v0.10.2 From 590232a7150674b2036291eaefce085f3f9659c8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:30:44 -0300 Subject: [LLC]: Add sysctl support for the LLC timeouts Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 3a29a9f..fc8e367 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -202,7 +202,8 @@ enum NET_TR=14, NET_DECNET=15, NET_ECONET=16, - NET_SCTP=17, + NET_SCTP=17, + NET_LLC=18, }; /* /proc/sys/kernel/random */ @@ -522,6 +523,29 @@ enum { NET_IPX_FORWARDING=2 }; +/* /proc/sys/net/llc */ +enum { + NET_LLC2=1, + NET_LLC_STATION=2, +}; + +/* /proc/sys/net/llc/llc2 */ +enum { + NET_LLC2_TIMEOUT=1, +}; + +/* /proc/sys/net/llc/station */ +enum { + NET_LLC_STATION_ACK_TIMEOUT=1, +}; + +/* /proc/sys/net/llc/llc2/timeout */ +enum { + NET_LLC2_ACK_TIMEOUT=1, + NET_LLC2_P_TIMEOUT=2, + NET_LLC2_REJ_TIMEOUT=3, + NET_LLC2_BUSY_TIMEOUT=4, +}; /* /proc/sys/net/appletalk */ enum { diff --git a/include/net/llc.h b/include/net/llc.h index 71769a5..8b8e2be 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -98,4 +98,11 @@ extern void llc_proc_exit(void); #define llc_proc_init() (0) #define llc_proc_exit() do { } while(0) #endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_SYSCTL +extern int llc_sysctl_init(void); +extern void llc_sysctl_exit(void); +#else +#define llc_sysctl_init() (0) +#define llc_sysctl_exit() do { } while(0) +#endif /* CONFIG_SYSCTL */ #endif /* LLC_H */ diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index 8ad3bc2..8a8ff48 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -19,14 +19,14 @@ #define LLC_EVENT 1 #define LLC_PACKET 2 -#define LLC_P_TIME 2 -#define LLC_ACK_TIME 1 -#define LLC_REJ_TIME 3 -#define LLC_BUSY_TIME 3 +#define LLC2_P_TIME 2 +#define LLC2_ACK_TIME 1 +#define LLC2_REJ_TIME 3 +#define LLC2_BUSY_TIME 3 struct llc_timer { struct timer_list timer; - u16 expire; /* timer expire time */ + unsigned long expire; /* timer expire time */ }; struct llc_sock { diff --git a/net/llc/Makefile b/net/llc/Makefile index 5ebd4ed..4e260cf 100644 --- a/net/llc/Makefile +++ b/net/llc/Makefile @@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \ llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o llc2-$(CONFIG_PROC_FS) += llc_proc.o +llc2-$(CONFIG_SYSCTL) += sysctl_net_llc.o diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 95444f2..ef12534 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -877,22 +877,22 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, case LLC_OPT_ACK_TMR_EXP: if (opt > LLC_OPT_MAX_ACK_TMR_EXP) goto out; - llc->ack_timer.expire = opt; + llc->ack_timer.expire = opt * HZ; break; case LLC_OPT_P_TMR_EXP: if (opt > LLC_OPT_MAX_P_TMR_EXP) goto out; - llc->pf_cycle_timer.expire = opt; + llc->pf_cycle_timer.expire = opt * HZ; break; case LLC_OPT_REJ_TMR_EXP: if (opt > LLC_OPT_MAX_REJ_TMR_EXP) goto out; - llc->rej_sent_timer.expire = opt; + llc->rej_sent_timer.expire = opt * HZ; break; case LLC_OPT_BUSY_TMR_EXP: if (opt > LLC_OPT_MAX_BUSY_TMR_EXP) goto out; - llc->busy_state_timer.expire = opt; + llc->busy_state_timer.expire = opt * HZ; break; case LLC_OPT_TX_WIN: if (opt > LLC_OPT_MAX_WIN) @@ -942,17 +942,17 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, goto out; switch (optname) { case LLC_OPT_RETRY: - val = llc->n2; break; + val = llc->n2; break; case LLC_OPT_SIZE: - val = llc->n1; break; + val = llc->n1; break; case LLC_OPT_ACK_TMR_EXP: - val = llc->ack_timer.expire; break; + val = llc->ack_timer.expire / HZ; break; case LLC_OPT_P_TMR_EXP: - val = llc->pf_cycle_timer.expire; break; + val = llc->pf_cycle_timer.expire / HZ; break; case LLC_OPT_REJ_TMR_EXP: - val = llc->rej_sent_timer.expire; break; + val = llc->rej_sent_timer.expire / HZ; break; case LLC_OPT_BUSY_TMR_EXP: - val = llc->busy_state_timer.expire; break; + val = llc->busy_state_timer.expire / HZ; break; case LLC_OPT_TX_WIN: val = llc->k; break; case LLC_OPT_RX_WIN: @@ -999,6 +999,13 @@ static struct proto_ops llc_ui_ops = { extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); +static char llc_proc_err_msg[] __initdata = + KERN_CRIT "LLC: Unable to register the proc_fs entries\n"; +static char llc_sysctl_err_msg[] __initdata = + KERN_CRIT "LLC: Unable to register the sysctl entries\n"; +static char llc_sock_err_msg[] __initdata = + KERN_CRIT "LLC: Unable to register the network family\n"; + static int __init llc2_init(void) { int rc = proto_register(&llc_proto, 0); @@ -1010,13 +1017,28 @@ static int __init llc2_init(void) llc_station_init(); llc_ui_sap_last_autoport = LLC_SAP_DYN_START; rc = llc_proc_init(); - if (rc != 0) + if (rc != 0) { + printk(llc_proc_err_msg); goto out_unregister_llc_proto; - sock_register(&llc_ui_family_ops); + } + rc = llc_sysctl_init(); + if (rc) { + printk(llc_sysctl_err_msg); + goto out_proc; + } + rc = sock_register(&llc_ui_family_ops); + if (rc) { + printk(llc_sock_err_msg); + goto out_sysctl; + } llc_add_pack(LLC_DEST_SAP, llc_sap_handler); llc_add_pack(LLC_DEST_CONN, llc_conn_handler); out: return rc; +out_sysctl: + llc_sysctl_exit(); +out_proc: + llc_proc_exit(); out_unregister_llc_proto: proto_unregister(&llc_proto); goto out; @@ -1029,6 +1051,7 @@ static void __exit llc2_exit(void) llc_remove_pack(LLC_DEST_CONN); sock_unregister(PF_LLC); llc_proc_exit(); + llc_sysctl_exit(); proto_unregister(&llc_proto); } diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 50c827e..a4daa91 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -620,7 +620,7 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb) if (!llc->remote_busy_flag) { llc->remote_busy_flag = 1; mod_timer(&llc->busy_state_timer.timer, - jiffies + llc->busy_state_timer.expire * HZ); + jiffies + llc->busy_state_timer.expire); } return 0; } @@ -853,7 +853,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb) llc_conn_set_p_flag(sk, 1); mod_timer(&llc->pf_cycle_timer.timer, - jiffies + llc->pf_cycle_timer.expire * HZ); + jiffies + llc->pf_cycle_timer.expire); return 0; } @@ -1131,7 +1131,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb) { struct llc_sock *llc = llc_sk(sk); - mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ); + mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire); return 0; } @@ -1140,7 +1140,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(sk); mod_timer(&llc->rej_sent_timer.timer, - jiffies + llc->rej_sent_timer.expire * HZ); + jiffies + llc->rej_sent_timer.expire); return 0; } @@ -1151,7 +1151,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk, if (!timer_pending(&llc->ack_timer.timer)) mod_timer(&llc->ack_timer.timer, - jiffies + llc->ack_timer.expire * HZ); + jiffies + llc->ack_timer.expire); return 0; } @@ -1199,7 +1199,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb) } if (unacked) mod_timer(&llc->ack_timer.timer, - jiffies + llc->ack_timer.expire * HZ); + jiffies + llc->ack_timer.expire); } else if (llc->failed_data_req) { u8 f_bit; diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index ce7b893..d3783f8 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, /* Offset table on connection states transition diagram */ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; +int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ; +int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ; +int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ; +int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ; + /** * llc_conn_state_process - sends event to connection state machine * @sk: connection @@ -799,22 +804,22 @@ static void llc_sk_init(struct sock* sk) llc->dec_step = llc->connect_step = 1; init_timer(&llc->ack_timer.timer); - llc->ack_timer.expire = LLC_ACK_TIME; + llc->ack_timer.expire = sysctl_llc2_ack_timeout; llc->ack_timer.timer.data = (unsigned long)sk; llc->ack_timer.timer.function = llc_conn_ack_tmr_cb; init_timer(&llc->pf_cycle_timer.timer); - llc->pf_cycle_timer.expire = LLC_P_TIME; + llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout; llc->pf_cycle_timer.timer.data = (unsigned long)sk; llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb; init_timer(&llc->rej_sent_timer.timer); - llc->rej_sent_timer.expire = LLC_REJ_TIME; + llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout; llc->rej_sent_timer.timer.data = (unsigned long)sk; llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb; init_timer(&llc->busy_state_timer.timer); - llc->busy_state_timer.expire = LLC_BUSY_TIME; + llc->busy_state_timer.expire = sysctl_llc2_busy_timeout; llc->busy_state_timer.timer.data = (unsigned long)sk; llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb; diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 85a7ac2..2d764b0 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -50,6 +50,10 @@ struct llc_station { struct sk_buff_head mac_pdu_q; }; +#define LLC_STATION_ACK_TIME (3 * HZ) + +int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME; + /* Types of events (possible values in 'ev->type') */ #define LLC_STATION_EV_TYPE_SIMPLE 1 #define LLC_STATION_EV_TYPE_CONDITION 2 @@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb) static int llc_station_ac_start_ack_timer(struct sk_buff *skb) { - mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ); + mod_timer(&llc_main_station.ack_timer, + jiffies + sysctl_llc_station_ack_timeout); return 0; } @@ -687,7 +692,8 @@ int __init llc_station_init(void) init_timer(&llc_main_station.ack_timer); llc_main_station.ack_timer.data = (unsigned long)&llc_main_station; llc_main_station.ack_timer.function = llc_station_ack_tmr_cb; - + llc_main_station.ack_timer.expires = jiffies + + sysctl_llc_station_ack_timeout; skb = alloc_skb(0, GFP_ATOMIC); if (!skb) goto out; @@ -695,7 +701,6 @@ int __init llc_station_init(void) llc_set_station_handler(llc_station_rcv); ev = llc_station_ev(skb); memset(ev, 0, sizeof(*ev)); - llc_main_station.ack_timer.expires = jiffies + 3 * HZ; llc_main_station.maximum_retry = 1; llc_main_station.state = LLC_STATION_STATE_DOWN; ev->type = LLC_STATION_EV_TYPE_SIMPLE; diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c new file mode 100644 index 0000000..4d99d2f --- /dev/null +++ b/net/llc/sysctl_net_llc.c @@ -0,0 +1,136 @@ +/* + * sysctl_net_llc.c: sysctl interface to LLC net subsystem. + * + * Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include + +#ifndef CONFIG_SYSCTL +#error This file should not be compiled without CONFIG_SYSCTL defined +#endif + +extern int sysctl_llc2_ack_timeout; +extern int sysctl_llc2_busy_timeout; +extern int sysctl_llc2_p_timeout; +extern int sysctl_llc2_rej_timeout; +extern int sysctl_llc_station_ack_timeout; + +static struct ctl_table llc2_timeout_table[] = { + { + .ctl_name = NET_LLC2_ACK_TIMEOUT, + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, + .maxlen = sizeof(long), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { + .ctl_name = NET_LLC2_BUSY_TIMEOUT, + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, + .maxlen = sizeof(long), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { + .ctl_name = NET_LLC2_P_TIMEOUT, + .procname = "p", + .data = &sysctl_llc2_p_timeout, + .maxlen = sizeof(long), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { + .ctl_name = NET_LLC2_REJ_TIMEOUT, + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, + .maxlen = sizeof(long), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { 0 }, +}; + +static struct ctl_table llc_station_table[] = { + { + .ctl_name = NET_LLC_STATION_ACK_TIMEOUT, + .procname = "ack_timeout", + .data = &sysctl_llc_station_ack_timeout, + .maxlen = sizeof(long), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, + { 0 }, +}; + +static struct ctl_table llc2_dir_timeout_table[] = { + { + .ctl_name = NET_LLC2, + .procname = "timeout", + .mode = 0555, + .child = llc2_timeout_table, + }, + { 0 }, +}; + +static struct ctl_table llc_table[] = { + { + .ctl_name = NET_LLC2, + .procname = "llc2", + .mode = 0555, + .child = llc2_dir_timeout_table, + }, + { + .ctl_name = NET_LLC_STATION, + .procname = "station", + .mode = 0555, + .child = llc_station_table, + }, + { 0 }, +}; + +static struct ctl_table llc_dir_table[] = { + { + .ctl_name = NET_LLC, + .procname = "llc", + .mode = 0555, + .child = llc_table, + }, + { 0 }, +}; + +static struct ctl_table llc_root_table[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = llc_dir_table, + }, + { 0 }, +}; + +static struct ctl_table_header *llc_table_header; + +int __init llc_sysctl_init(void) +{ + llc_table_header = register_sysctl_table(llc_root_table, 1); + + return llc_table_header ? 0 : -ENOMEM; +} + +void llc_sysctl_exit(void) +{ + if (llc_table_header) { + unregister_sysctl_table(llc_table_header); + llc_table_header = NULL; + } +} -- cgit v0.10.2 From 249ff1c6d35fd32ca945967c3f0b948210a96baa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:32:10 -0300 Subject: [LLC]: Use some more likely/unlikely Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ef12534..7e9cf32 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -116,12 +116,12 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock) struct llc_sock* llc = llc_sk(sk); int rc = 0; - if (llc_data_accept_state(llc->state) || llc->p_flag) { + if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) { long timeout = sock_sndtimeo(sk, noblock); rc = llc_ui_wait_for_busy_core(sk, timeout); } - if (!rc) + if (unlikely(!rc)) rc = llc_build_and_send_pkt(sk, skb); return rc; } @@ -762,15 +762,13 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua)) goto out; rc = llc_ui_send_data(sk, skb, noblock); - if (rc) - dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc); out: - if (rc) + if (rc) { kfree_skb(skb); release: - if (rc) dprintk("%s: failed sending from %02X to %02X: %d\n", __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc); + } release_sock(sk); return rc ? : copied; } diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index a4daa91..9d9b6c8a 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -221,7 +221,7 @@ int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_disc_cmd(nskb, 1); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); llc_conn_ac_set_p_flag_1(sk, skb); @@ -248,7 +248,7 @@ int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_dm_rsp(nskb, f_bit); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -272,7 +272,7 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_dm_rsp(nskb, 1); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -305,7 +305,7 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, llc->vR, INCORRECT); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -331,7 +331,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_frmr_rsp(nskb, pdu, 0, llc->vS, llc->vR, INCORRECT); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -360,7 +360,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS, llc->vR, INCORRECT); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -381,7 +381,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); - if (!rc) { + if (likely(!rc)) { llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -398,7 +398,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); - if (!rc) { + if (likely(!rc)) { llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -415,7 +415,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); - if (!rc) { + if (likely(!rc)) { llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -447,7 +447,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (!rc) + if (likely(!rc)) llc_conn_send_pdu(sk, nskb); else kfree_skb(skb); @@ -482,7 +482,7 @@ int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -506,7 +506,7 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rej_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -530,7 +530,7 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rej_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -554,7 +554,7 @@ int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -578,7 +578,7 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -602,7 +602,7 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -638,7 +638,7 @@ int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -662,7 +662,7 @@ int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -687,7 +687,7 @@ int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -711,7 +711,7 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 1, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -735,7 +735,7 @@ int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -759,7 +759,7 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -796,7 +796,7 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_sabme_cmd(nskb, 1); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); llc_conn_set_p_flag(sk, 1); @@ -824,7 +824,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_ua_rsp(nskb, f_bit); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } @@ -924,7 +924,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR); rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac); - if (!rc) { + if (likely(!rc)) { llc_conn_send_pdu(sk, skb); llc_conn_ac_inc_vs_by_1(sk, skb); } @@ -978,7 +978,7 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, llc->daddr.lsap, LLC_PDU_RSP); llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR); rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac); - if (rc) + if (unlikely(rc)) goto free; llc_conn_send_pdu(sk, nskb); } diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index 0f84f66..764dbd7 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb) int rc = -ECONNABORTED; struct llc_sock *llc = llc_sk(sk); - if (llc->state == LLC_CONN_STATE_ADM) + if (unlikely(llc->state == LLC_CONN_STATE_ADM)) goto out; rc = -EBUSY; - if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */ - llc->failed_data_req = 1; - goto out; - } - if (llc->p_flag) { + if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */ + llc->p_flag)) { llc->failed_data_req = 1; goto out; } diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c index ab5784c..b4d55b6 100644 --- a/net/llc/llc_output.c +++ b/net/llc/llc_output.c @@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, dsap, LLC_PDU_CMD); llc_pdu_init_as_ui_cmd(skb); rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(skb); return rc; } diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index 270b2f2..6acdebf 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_ui_cmd(skb); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(skb); return rc; } @@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(skb); return rc; } @@ -110,7 +110,7 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) LLC_PDU_RSP); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(nskb); out: return rc; @@ -134,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) ev->daddr.lsap, LLC_PDU_CMD); llc_pdu_init_as_test_cmd(skb); rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(skb); return rc; } @@ -155,7 +155,7 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) LLC_PDU_RSP); llc_pdu_init_as_test_rsp(nskb, skb); rc = llc_mac_hdr_init(nskb, mac_sa, mac_da); - if (!rc) + if (likely(!rc)) rc = dev_queue_xmit(nskb); out: return rc; diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 2d764b0..ec4693f 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -261,7 +261,7 @@ static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa); - if (rc) + if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); out: @@ -285,7 +285,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); - if (rc) + if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); out: @@ -309,7 +309,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_test_rsp(nskb, skb); rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); - if (rc) + if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); out: -- cgit v0.10.2 From afdbe35787ea3390af0f1dd38b3dd9d8a8d313e7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:37:07 -0300 Subject: [LLC]: Use sk_wait_data Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 7e9cf32..f536369 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -39,7 +39,6 @@ static struct proto_ops llc_ui_ops; static int llc_ui_wait_for_conn(struct sock *sk, long timeout); static int llc_ui_wait_for_disc(struct sock *sk, long timeout); -static int llc_ui_wait_for_data(struct sock *sk, long timeout); static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout); #if 0 @@ -524,16 +523,19 @@ static int llc_ui_wait_for_conn(struct sock *sk, long timeout) return timeout; } -static int llc_ui_wait_for_data(struct sock *sk, long timeout) +static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) { DEFINE_WAIT(wait); - int rc = 0; + struct llc_sock *llc = llc_sk(sk); + int rc; while (1) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + rc = 0; if (sk_wait_event(sk, &timeout, (sk->sk_shutdown & RCV_SHUTDOWN) || - (!skb_queue_empty(&sk->sk_receive_queue)))) + (!llc_data_accept_state(llc->state) && + !llc->p_flag))) break; rc = -ERESTARTSYS; if (signal_pending(current)) @@ -541,34 +543,36 @@ static int llc_ui_wait_for_data(struct sock *sk, long timeout) rc = -EAGAIN; if (!timeout) break; - rc = 0; } finish_wait(sk->sk_sleep, &wait); return rc; } -static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) +int llc_wait_data(struct sock *sk, long timeo) { - DEFINE_WAIT(wait); - struct llc_sock *llc = llc_sk(sk); int rc; while (1) { - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + /* + * POSIX 1003.1g mandates this order. + */ + if (sk->sk_err) { + rc = sock_error(sk); + break; + } rc = 0; - if (sk_wait_event(sk, &timeout, - (sk->sk_shutdown & RCV_SHUTDOWN) || - (!llc_data_accept_state(llc->state) && - !llc->p_flag))) + if (sk->sk_shutdown & RCV_SHUTDOWN) break; - rc = -ERESTARTSYS; + rc = -EAGAIN; + if (!timeo) + break; + rc = sock_intr_errno(timeo); if (signal_pending(current)) break; - rc = -EAGAIN; - if (!timeout) + rc = 0; + if (sk_wait_data(sk, &timeo)) break; } - finish_wait(sk->sk_sleep, &wait); return rc; } @@ -599,7 +603,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) goto out; /* wait for a connection to arrive. */ if (skb_queue_empty(&sk->sk_receive_queue)) { - rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); + rc = llc_wait_data(sk, sk->sk_rcvtimeo); if (rc) goto out; } @@ -658,7 +662,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); lock_sock(sk); if (skb_queue_empty(&sk->sk_receive_queue)) { - rc = llc_ui_wait_for_data(sk, sock_rcvtimeo(sk, noblock)); + rc = llc_wait_data(sk, sock_rcvtimeo(sk, noblock)); if (rc) goto out; } -- cgit v0.10.2 From 04e4223f44b89e50f275cb6b95a58ebe2c4909be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:40:59 -0300 Subject: [LLC]: Do better struct sock accounting on skbs Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h index 6dd4cdc..9dcfcf4 100644 --- a/include/net/llc_sap.h +++ b/include/net/llc_sap.h @@ -12,11 +12,13 @@ * See the GNU General Public License for more details. */ struct llc_sap; -struct sk_buff; struct net_device; +struct sk_buff; +struct sock; extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim); +extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, + unsigned char prim); extern struct sk_buff *llc_alloc_frame(struct net_device *dev); extern void llc_build_and_send_test_pkt(struct llc_sap *sap, diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f536369..ad9aad8 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -628,7 +628,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags) /* put original socket back into a clean listen state. */ sk->sk_state = TCP_LISTEN; sk->sk_ack_backlog--; - skb->sk = NULL; dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__, llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap); frees: @@ -740,7 +739,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, lock_sock(sk); if (!skb) goto release; - skb->sk = sk; skb->dev = llc->dev; skb->protocol = llc_proto_type(addr->sllc_arphrd); skb_reserve(skb, hdrlen); diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 9d9b6c8a..c1e7510 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -1335,7 +1335,7 @@ static void llc_conn_tmr_common_cb(unsigned long timeout_data, u8 type) if (skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); - skb->sk = sk; + skb_set_owner_r(skb, sk); ev->type = type; llc_process_tmr_ev(sk, skb); } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index d3783f8..9f0e10e 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -90,8 +90,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) switch (ev->ind_prim) { case LLC_DATA_PRIM: - llc_save_primitive(skb, LLC_DATA_PRIM); - if (sock_queue_rcv_skb(sk, skb)) { + llc_save_primitive(sk, skb, LLC_DATA_PRIM); + if (unlikely(sock_queue_rcv_skb(sk, skb))) { /* * shouldn't happen */ @@ -103,6 +103,11 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) case LLC_CONN_PRIM: { struct sock *parent = skb->sk; + skb_orphan(skb); + /* + * Set the skb->sk to the new struct sock, so that at accept + * type the upper layer can get the newly created struct sock. + */ skb->sk = sk; skb_queue_tail(&parent->sk_receive_queue, skb); sk->sk_state_change(parent); @@ -702,10 +707,9 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) memcpy(&llc->daddr, &saddr, sizeof(llc->daddr)); llc_sap_add_socket(sap, sk); sock_hold(sk); + skb_set_owner_r(skb, parent); sock_put(parent); - skb->sk = parent; - } else - skb->sk = sk; + } bh_lock_sock(sk); if (!sock_owned_by_user(sk)) llc_conn_rcv(sk, skb); diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 0adaa28..9f064b3 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -45,12 +45,12 @@ struct sk_buff *llc_alloc_frame(struct net_device *dev) return skb; } -void llc_save_primitive(struct sk_buff* skb, u8 prim) +void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) { struct sockaddr_llc *addr = llc_ui_skb_cb(skb); /* save primitive for use by the user. */ - addr->sllc_family = skb->sk->sk_family; + addr->sllc_family = sk->sk_family; addr->sllc_arphrd = skb->dev->type; addr->sllc_test = prim == LLC_TEST_PRIM; addr->sllc_xid = prim == LLC_XID_PRIM; @@ -190,7 +190,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) if (skb->sk->sk_state == TCP_LISTEN) kfree_skb(skb); else { - llc_save_primitive(skb, ev->prim); + llc_save_primitive(skb->sk, skb, ev->prim); /* queue skb to the user. */ if (sock_queue_rcv_skb(skb->sk, skb)) @@ -309,7 +309,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb) sk = llc_lookup_dgram(sap, &laddr); if (sk) { - skb->sk = sk; + skb_set_owner_r(skb, sk); llc_sap_rcv(sap, skb); sock_put(sk); } else -- cgit v0.10.2 From 6e2144b76840be09924de1626e2dcd7b315f75b3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 04:43:05 -0300 Subject: [LLC]: Use refcounting with struct llc_sap Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc.h b/include/net/llc.h index 8b8e2be..93e5b44 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -17,6 +17,8 @@ #include #include +#include + struct net_device; struct packet_type; struct sk_buff; @@ -44,6 +46,7 @@ struct llc_sap { unsigned char state; unsigned char p_bit; unsigned char f_bit; + atomic_t refcnt; int (*rcv_func)(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, @@ -81,7 +84,18 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)); -extern void llc_sap_close(struct llc_sap *sap); +static inline void llc_sap_hold(struct llc_sap *sap) +{ + atomic_inc(&sap->refcnt); +} + +static inline void llc_sap_put(struct llc_sap *sap) +{ + extern void llc_sap_close(struct llc_sap *sap); + + if (atomic_dec_and_test(&sap->refcnt)) + llc_sap_close(sap); +} extern struct llc_sap *llc_sap_find(unsigned char sap_value); diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index 8a8ff48..b288921 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -115,5 +115,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk); extern u8 llc_data_accept_state(u8 state); extern void llc_build_offset_table(void); -extern int llc_release_sockets(struct llc_sap *sap); #endif /* LLC_CONN_H */ diff --git a/net/802/p8022.c b/net/802/p8022.c index b24817c..2530f35 100644 --- a/net/802/p8022.c +++ b/net/802/p8022.c @@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type, void unregister_8022_client(struct datalink_proto *proto) { - llc_sap_close(proto->sap); + llc_sap_put(proto->sap); kfree(proto); } diff --git a/net/802/psnap.c b/net/802/psnap.c index ab80b1f..4d63894 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c @@ -106,7 +106,7 @@ module_init(snap_init); static void __exit snap_exit(void) { - llc_sap_close(snap_sap); + llc_sap_put(snap_sap); } module_exit(snap_exit); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ad9aad8..a75b8f2 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -21,6 +21,7 @@ * See the GNU General Public License for more details. */ #include +#include #include #include #include @@ -188,10 +189,6 @@ static int llc_ui_release(struct socket *sock) if (!sock_flag(sk, SOCK_ZAPPED)) llc_sap_remove_socket(llc->sap, sk); release_sock(sk); - if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) { - llc_release_sockets(llc->sap); - llc_sap_close(llc->sap); - } if (llc->dev) dev_put(llc->dev); sock_put(sk); @@ -220,6 +217,7 @@ static int llc_ui_autoport(void) llc_ui_sap_last_autoport = i + 2; goto out; } + llc_sap_put(sap); } llc_ui_sap_last_autoport = LLC_SAP_DYN_START; tries++; @@ -310,6 +308,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) rc = -EBUSY; /* some other network layer is using the sap */ if (!sap) goto out; + llc_sap_hold(sap); } else { struct llc_addr laddr, daddr; struct sock *ask; @@ -326,7 +325,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) ask = llc_lookup_established(sap, &daddr, &laddr); if (ask) { sock_put(ask); - goto out; + goto out_put; } } llc->laddr.lsap = addr->sllc_sap; @@ -336,6 +335,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) llc_sap_add_socket(sap, sk); sock_reset_flag(sk, SOCK_ZAPPED); rc = 0; +out_put: + llc_sap_put(sap); out: return rc; } diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index c1e7510..05236c2 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -75,6 +75,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) llc->dev = skb->dev; ev->ind_prim = LLC_CONN_PRIM; rc = 0; + llc_sap_put(sap); } return rc; } diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 9f0e10e..ab9e6d7 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -633,6 +633,7 @@ static int llc_find_offset(int state, int ev_type) */ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) { + llc_sap_hold(sap); write_lock_bh(&sap->sk_list.lock); llc_sk(sk)->sap = sap; sk_add_node(sk, &sap->sk_list.list); @@ -652,6 +653,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) write_lock_bh(&sap->sk_list.lock); sk_del_node_init(sk); write_unlock_bh(&sap->sk_list.lock); + llc_sap_put(sap); } /** @@ -731,32 +733,6 @@ static atomic_t llc_sock_nr; #endif /** - * llc_release_sockets - releases all sockets in a sap - * @sap: sap to release its sockets - * - * Releases all connections of a sap. Returns 0 if all actions complete - * successfully, nonzero otherwise - */ -int llc_release_sockets(struct llc_sap *sap) -{ - int rc = 0; - struct sock *sk; - struct hlist_node *node; - - write_lock_bh(&sap->sk_list.lock); - - sk_for_each(sk, node, &sap->sk_list.list) { - llc_sk(sk)->state = LLC_CONN_STATE_TEMP; - - if (llc_send_disc(sk)) - rc = 1; - } - - write_unlock_bh(&sap->sk_list.lock); - return rc; -} - -/** * llc_backlog_rcv - Processes rx frames and expired timers. * @sk: LLC sock (p8022 connection) * @skb: queued rx frame or event diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 9727455..9ccff12 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void) sap->state = LLC_SAP_STATE_ACTIVE; memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); rwlock_init(&sap->sk_list.lock); + atomic_set(&sap->refcnt, 1); } return sap; } @@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void) */ static void llc_add_sap(struct llc_sap *sap) { - write_lock_bh(&llc_sap_list_lock); list_add_tail(&sap->node, &llc_sap_list); - write_unlock_bh(&llc_sap_list_lock); } /** @@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap) write_unlock_bh(&llc_sap_list_lock); } +struct llc_sap *__llc_sap_find(unsigned char sap_value) +{ + struct llc_sap* sap; + + list_for_each_entry(sap, &llc_sap_list, node) + if (sap->laddr.lsap == sap_value) + goto out; + sap = NULL; +out: + return sap; +} + /** * llc_sap_find - searchs a SAP in station * @sap_value: sap to be found * * Searchs for a sap in the sap list of the LLC's station upon the sap ID. + * If the sap is found it will be refcounted and the user will have to do + * a llc_sap_put after use. * Returns the sap or %NULL if not found. */ struct llc_sap *llc_sap_find(unsigned char sap_value) @@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) struct llc_sap* sap; read_lock_bh(&llc_sap_list_lock); - list_for_each_entry(sap, &llc_sap_list, node) - if (sap->laddr.lsap == sap_value) - goto out; - sap = NULL; -out: + sap = __llc_sap_find(sap_value); + if (sap) + llc_sap_hold(sap); read_unlock_bh(&llc_sap_list_lock); return sap; } @@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap, struct packet_type *pt, struct net_device *orig_dev)) { - struct llc_sap *sap = llc_sap_find(lsap); + struct llc_sap *sap = NULL; - if (sap) { /* SAP already exists */ - sap = NULL; + write_lock_bh(&llc_sap_list_lock); + if (__llc_sap_find(lsap)) /* SAP already exists */ goto out; - } sap = llc_sap_alloc(); if (!sap) goto out; sap->laddr.lsap = lsap; sap->rcv_func = func; + llc_sap_hold(sap); llc_add_sap(sap); out: + write_unlock_bh(&llc_sap_list_lock); return sap; } diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 60c1aca..789eec4 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -166,17 +166,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, */ if (sap->rcv_func) { sap->rcv_func(skb, dev, pt, orig_dev); - goto out; + goto out_put; } dest = llc_pdu_type(skb); if (unlikely(!dest || !llc_type_handlers[dest - 1])) - goto drop; + goto drop_put; llc_type_handlers[dest - 1](sap, skb); +out_put: + llc_sap_put(sap); out: return 0; drop: kfree_skb(skb); goto out; +drop_put: + kfree_skb(skb); + goto out_put; handle_station: if (!llc_station_handler) goto drop; -- cgit v0.10.2 From cf309e3fb863b7a245b91f816193957f6daf786f Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Thu, 22 Sep 2005 04:44:55 -0300 Subject: [LLC]: Fix for Bugzilla ticket #5156 Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/core/dev.c b/net/core/dev.c index c01511e..37c8810 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha) return dev; } +EXPORT_SYMBOL(dev_getbyhwaddr); + struct net_device *dev_getfirstbyhwtype(unsigned short type) { struct net_device *dev; diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index a75b8f2..0607cd3 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -296,6 +296,12 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) rc = -EAFNOSUPPORT; if (unlikely(addr->sllc_family != AF_LLC)) goto out; + rc = -ENODEV; + rtnl_lock(); + llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac); + rtnl_unlock(); + if (!llc->dev) + goto out; if (!addr->sllc_sap) { rc = -EUSERS; addr->sllc_sap = llc_ui_autoport(); -- cgit v0.10.2 From 5085b4a5492f4f8bd32d0cc5b1cad4bf522c2e1a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 00:45:41 -0700 Subject: [SPARC64]: Do not allocate OBP page tables using bootmem Just allocate them physically starting from the end of the kernel image. This incredibly simplifies our MM bootstrap in that we don't need any mappings in the linear PAGE_OFFSET area working in order to bootstrap ourselves and take over the trap table from the firmware. Many further simplifications are possible now, and this also sets the stage for CONFIG_DEBUG_PAGEALLOC support. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 11d2187..598bfb3 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -324,14 +324,59 @@ unsigned long kern_locked_tte_data; unsigned long prom_pmd_phys __read_mostly; unsigned int swapper_pgd_zero __read_mostly; -void __init early_pgtable_allocfail(char *type) +/* Allocate power-of-2 aligned chunks from the end of the + * kernel image. Return physical address. + */ +static inline unsigned long early_alloc_phys(unsigned long size) { - prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type); - prom_halt(); + unsigned long base; + + BUILD_BUG_ON(size & (size - 1)); + + kern_size = (kern_size + (size - 1)) & ~(size - 1); + base = kern_base + kern_size; + kern_size += size; + + return base; +} + +static inline unsigned long load_phys32(unsigned long pa) +{ + unsigned long val; + + __asm__ __volatile__("lduwa [%1] %2, %0" + : "=&r" (val) + : "r" (pa), "i" (ASI_PHYS_USE_EC)); + + return val; +} + +static inline unsigned long load_phys64(unsigned long pa) +{ + unsigned long val; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=&r" (val) + : "r" (pa), "i" (ASI_PHYS_USE_EC)); + + return val; +} + +static inline void store_phys32(unsigned long pa, unsigned long val) +{ + __asm__ __volatile__("stwa %0, [%1] %2" + : /* no outputs */ + : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); +} + +static inline void store_phys64(unsigned long pa, unsigned long val) +{ + __asm__ __volatile__("stxa %0, [%1] %2" + : /* no outputs */ + : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); } #define BASE_PAGE_SIZE 8192 -static pmd_t *prompmd; /* * Translate PROM's mapping we capture at boot time into physical address. @@ -339,33 +384,34 @@ static pmd_t *prompmd; */ unsigned long prom_virt_to_phys(unsigned long promva, int *error) { - pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff); - pte_t *ptep; + unsigned long pmd_phys = (prom_pmd_phys + + ((promva >> 23) & 0x7ff) * sizeof(pmd_t)); + unsigned long pte_phys; + pmd_t pmd_ent; + pte_t pte_ent; unsigned long base; - if (pmd_none(*pmdp)) { + pmd_val(pmd_ent) = load_phys32(pmd_phys); + if (pmd_none(pmd_ent)) { if (error) *error = 1; - return(0); + return 0; } - ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff); - if (!pte_present(*ptep)) { + + pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; + pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t); + pte_val(pte_ent) = load_phys64(pte_phys); + if (!pte_present(pte_ent)) { if (error) *error = 1; - return(0); + return 0; } if (error) { *error = 0; - return(pte_val(*ptep)); + return pte_val(pte_ent); } - base = pte_val(*ptep) & _PAGE_PADDR; - return(base + (promva & (BASE_PAGE_SIZE - 1))); -} - -static inline int in_obp_range(unsigned long vaddr) -{ - return (vaddr >= LOW_OBP_ADDRESS && - vaddr < HI_OBP_ADDRESS); + base = pte_val(pte_ent) & _PAGE_PADDR; + return (base + (promva & (BASE_PAGE_SIZE - 1))); } /* The obp translations are saved based on 8k pagesize, since obp can @@ -378,22 +424,25 @@ static void build_obp_range(unsigned long start, unsigned long end, unsigned lon unsigned long vaddr; for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { - unsigned long val; - pmd_t *pmdp; - pte_t *ptep; - - pmdp = prompmd + ((vaddr >> 23) & 0x7ff); - if (pmd_none(*pmdp)) { - ptep = __alloc_bootmem(BASE_PAGE_SIZE, - BASE_PAGE_SIZE, - bootmap_base); - if (ptep == NULL) - early_pgtable_allocfail("pte"); - memset(ptep, 0, BASE_PAGE_SIZE); - pmd_set(pmdp, ptep); + unsigned long val, pte_phys, pmd_phys; + pmd_t pmd_ent; + int i; + + pmd_phys = (prom_pmd_phys + + (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t))); + pmd_val(pmd_ent) = load_phys32(pmd_phys); + if (pmd_none(pmd_ent)) { + pte_phys = early_alloc_phys(BASE_PAGE_SIZE); + + for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++) + store_phys64(pte_phys+i*sizeof(pte_t),0); + + pmd_val(pmd_ent) = pte_phys >> 11UL; + store_phys32(pmd_phys, pmd_val(pmd_ent)); } - ptep = (pte_t *)__pmd_page(*pmdp) + - ((vaddr >> 13) & 0x3ff); + + pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; + pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t)); val = data; @@ -401,22 +450,27 @@ static void build_obp_range(unsigned long start, unsigned long end, unsigned lon if (tlb_type == spitfire) val &= ~0x0003fe0000000000UL; - set_pte_at(&init_mm, vaddr, - ptep, __pte(val | _PAGE_MODIFIED)); + store_phys64(pte_phys, val | _PAGE_MODIFIED); + data += BASE_PAGE_SIZE; } } +static inline int in_obp_range(unsigned long vaddr) +{ + return (vaddr >= LOW_OBP_ADDRESS && + vaddr < HI_OBP_ADDRESS); +} + #define OBP_PMD_SIZE 2048 static void build_obp_pgtable(int prom_trans_ents) { - int i; + unsigned long i; + + prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE); + for (i = 0; i < OBP_PMD_SIZE; i += 4) + store_phys32(prom_pmd_phys + i, 0); - prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, - bootmap_base); - if (prompmd == NULL) - early_pgtable_allocfail("pmd"); - memset(prompmd, 0, OBP_PMD_SIZE); for (i = 0; i < prom_trans_ents; i++) { unsigned long start, end; @@ -430,7 +484,6 @@ static void build_obp_pgtable(int prom_trans_ents) build_obp_range(start, end, prom_trans[i].data); } - prom_pmd_phys = __pa(prompmd); } /* Read OBP translations property into 'prom_trans[]'. @@ -1517,13 +1570,13 @@ void __init paging_init(void) swapper_pgd_zero = pgd_val(init_mm.pgd[0]); + /* Inherit non-locked OBP mappings. */ + inherit_prom_mappings(); + /* Setup bootmem... */ pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail); - /* Inherit non-locked OBP mappings. */ - inherit_prom_mappings(); - /* Ok, we can use our TLB miss and window trap handlers safely. * We need to do a quick peek here to see if we are on StarFire * or not, so setup_tba can setup the IRQ globals correctly (it -- cgit v0.10.2 From 5564af21ae7900889c5151e5b16bd42cdda11a77 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Thu, 22 Sep 2005 04:46:44 -0300 Subject: [LLC]: Fix for Bugzilla ticket #5157 Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 0607cd3..3361ae9 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -418,9 +418,9 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, rc = llc_ui_autobind(sock, addr); if (rc) goto out; - llc->daddr.lsap = addr->sllc_sap; - memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN); } + llc->daddr.lsap = addr->sllc_sap; + memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN); sock->state = SS_CONNECTING; sk->sk_state = TCP_SYN_SENT; llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap); -- cgit v0.10.2 From 096f0eb1dff326ddebfedeb128fb48d5b7ca75e1 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Thu, 22 Sep 2005 04:48:46 -0300 Subject: [LLC]: Fix llc_fixup_skb() bug llc_fixup_skb() had a bug dropping 3 bytes packets (like UA frames). Token ring doesn't pad these frames. Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 789eec4..8f3addf 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -99,15 +99,19 @@ out: static inline int llc_fixup_skb(struct sk_buff *skb) { u8 llc_len = 2; - struct llc_pdu_sn *pdu; + struct llc_pdu_un *pdu; if (unlikely(!pskb_may_pull(skb, sizeof(*pdu)))) return 0; - pdu = (struct llc_pdu_sn *)skb->data; + pdu = (struct llc_pdu_un *)skb->data; if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U) llc_len = 1; llc_len += 2; + + if (unlikely(!pskb_may_pull(skb, llc_len))) + return 0; + skb->h.raw += llc_len; skb_pull(skb, llc_len); if (skb->protocol == htons(ETH_P_802_2)) { -- cgit v0.10.2 From 0519d8fbabc4eb215a8263f29143ccd86c328157 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Thu, 22 Sep 2005 04:51:56 -0300 Subject: [TR]: Set correct frame type for SNAP packets Signed-off-by: Jochen Friedrich Signed-off-by: Arnaldo Carvalho de Melo diff --git a/net/802/tr.c b/net/802/tr.c index 1bb7dc1..1eaa3d1 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev) return trllc->ethertype; } - return ntohs(ETH_P_802_2); + return ntohs(ETH_P_TR_802_2); } /* -- cgit v0.10.2 From 2bdb3cb265830aee823444d115a8a84eca2b934e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 01:08:57 -0700 Subject: [SPARC64]: Remove unnecessary paging_init() cruft. Because we don't access the PAGE_OFFSET linear mappings any longer before we take over the trap table from the firmware, we don't need to load dummy mappings there into the TLB and we don't need the bootmap_base hack any longer either. While we are here, check for a larger than 8MB kernel and halt the boot with an error message. We know that doesn't work, so instead of failing mysteriously we should let the user know exactly what's wrong. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 598bfb3..92d0958 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -43,7 +43,7 @@ extern void device_scan(void); struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; -unsigned long *sparc64_valid_addr_bitmap; +unsigned long *sparc64_valid_addr_bitmap __read_mostly; /* Ugly, but necessary... -DaveM */ unsigned long phys_base __read_mostly; @@ -51,15 +51,6 @@ unsigned long kern_base __read_mostly; unsigned long kern_size __read_mostly; unsigned long pfn_base __read_mostly; -/* This is even uglier. We have a problem where the kernel may not be - * located at phys_base. However, initial __alloc_bootmem() calls need to - * be adjusted to be within the 4-8Megs that the kernel is mapped to, else - * those page mappings wont work. Things are ok after inherit_prom_mappings - * is called though. Dave says he'll clean this up some other time. - * -- BenC - */ -static unsigned long bootmap_base; - /* get_new_mmu_context() uses "cache + 1". */ DEFINE_SPINLOCK(ctx_alloc_lock); unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; @@ -1415,8 +1406,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) #endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); - bootmap_base = bootmap_pfn << PAGE_SHIFT; - /* Now register the available physical memory with the * allocator. */ @@ -1475,89 +1464,22 @@ static unsigned long last_valid_pfn; void __init paging_init(void) { extern pmd_t swapper_pmd_dir[1024]; - unsigned long alias_base = kern_base + PAGE_OFFSET; - unsigned long second_alias_page = 0; - unsigned long pt, flags, end_pfn, pages_avail; - unsigned long shift = alias_base - ((unsigned long)KERNBASE); + unsigned long end_pfn, pages_avail, shift; unsigned long real_end; set_bit(0, mmu_context_bmap); + shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); + real_end = (unsigned long)_end; if ((real_end > ((unsigned long)KERNBASE + 0x400000))) bigkernel = 1; -#ifdef CONFIG_BLK_DEV_INITRD - if (sparc_ramdisk_image || sparc_ramdisk_image64) - real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size)); -#endif - - /* We assume physical memory starts at some 4mb multiple, - * if this were not true we wouldn't boot up to this point - * anyways. - */ - pt = kern_base | _PAGE_VALID | _PAGE_SZ4MB; - pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; - local_irq_save(flags); - if (tlb_type == spitfire) { - __asm__ __volatile__( - " stxa %1, [%0] %3\n" - " stxa %2, [%5] %4\n" - " membar #Sync\n" - " flush %%g6\n" - " nop\n" - " nop\n" - " nop\n" - : /* No outputs */ - : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3) - : "memory"); - if (real_end >= KERNBASE + 0x340000) { - second_alias_page = alias_base + 0x400000; - __asm__ __volatile__( - " stxa %1, [%0] %3\n" - " stxa %2, [%5] %4\n" - " membar #Sync\n" - " flush %%g6\n" - " nop\n" - " nop\n" - " nop\n" - : /* No outputs */ - : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3) - : "memory"); - } - } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - __asm__ __volatile__( - " stxa %1, [%0] %3\n" - " stxa %2, [%5] %4\n" - " membar #Sync\n" - " flush %%g6\n" - " nop\n" - " nop\n" - " nop\n" - : /* No outputs */ - : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3)) - : "memory"); - if (real_end >= KERNBASE + 0x340000) { - second_alias_page = alias_base + 0x400000; - __asm__ __volatile__( - " stxa %1, [%0] %3\n" - " stxa %2, [%5] %4\n" - " membar #Sync\n" - " flush %%g6\n" - " nop\n" - " nop\n" - " nop\n" - : /* No outputs */ - : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (12<<3)) - : "memory"); - } + if ((real_end > ((unsigned long)KERNBASE + 0x800000))) { + prom_printf("paging_init: Kernel > 8MB, too large.\n"); + prom_halt(); } - local_irq_restore(flags); - - /* Now set kernel pgd to upper alias so physical page computations + + /* Set kernel pgd to upper alias so physical page computations * work. */ init_mm.pgd += ((shift) / (sizeof(pgd_t))); @@ -1568,15 +1490,11 @@ void __init paging_init(void) pud_set(pud_offset(&swapper_pg_dir[0], 0), swapper_pmd_dir + (shift / sizeof(pgd_t))); - swapper_pgd_zero = pgd_val(init_mm.pgd[0]); + swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); /* Inherit non-locked OBP mappings. */ inherit_prom_mappings(); - /* Setup bootmem... */ - pages_avail = 0; - last_valid_pfn = end_pfn = bootmem_init(&pages_avail); - /* Ok, we can use our TLB miss and window trap handlers safely. * We need to do a quick peek here to see if we are on StarFire * or not, so setup_tba can setup the IRQ globals correctly (it @@ -1589,13 +1507,12 @@ void __init paging_init(void) inherit_locked_prom_mappings(1); - /* We only created DTLB mapping of this stuff. */ - spitfire_flush_dtlb_nucleus_page(alias_base); - if (second_alias_page) - spitfire_flush_dtlb_nucleus_page(second_alias_page); - __flush_tlb_all(); + /* Setup bootmem... */ + pages_avail = 0; + last_valid_pfn = end_pfn = bootmem_init(&pages_avail); + { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; @@ -1757,8 +1674,7 @@ void __init mem_init(void) i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); i += 1; - sparc64_valid_addr_bitmap = (unsigned long *) - __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base); + sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3); if (sparc64_valid_addr_bitmap == NULL) { prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); prom_halt(); -- cgit v0.10.2 From 2928c19e1086e2f1e90d05931437ab6f1e4cfdc8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 05:14:33 -0300 Subject: [LLC]: Fix sparse warnings Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc.h b/include/net/llc.h index 93e5b44..1adb2ef 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -89,10 +89,10 @@ static inline void llc_sap_hold(struct llc_sap *sap) atomic_inc(&sap->refcnt); } +extern void llc_sap_close(struct llc_sap *sap); + static inline void llc_sap_put(struct llc_sap *sap) { - extern void llc_sap_close(struct llc_sap *sap); - if (atomic_dec_and_test(&sap->refcnt)) llc_sap_close(sap); } @@ -102,6 +102,9 @@ extern struct llc_sap *llc_sap_find(unsigned char sap_value); extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, unsigned char *dmac, unsigned char dsap); +extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); +extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); + extern int llc_station_init(void); extern void llc_station_exit(void); @@ -115,6 +118,12 @@ extern void llc_proc_exit(void); #ifdef CONFIG_SYSCTL extern int llc_sysctl_init(void); extern void llc_sysctl_exit(void); + +extern int sysctl_llc2_ack_timeout; +extern int sysctl_llc2_busy_timeout; +extern int sysctl_llc2_p_timeout; +extern int sysctl_llc2_rej_timeout; +extern int sysctl_llc_station_ack_timeout; #else #define llc_sysctl_init() (0) #define llc_sysctl_exit() do { } while(0) diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index b288921..e44f494 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -92,7 +92,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) return skb->cb[sizeof(skb->cb) - 1]; } -extern struct sock *llc_sk_alloc(int family, int priority, struct proto *prot); +extern struct sock *llc_sk_alloc(int family, unsigned int __nocast priority, + struct proto *prot); extern void llc_sk_free(struct sock *sk); extern void llc_sk_reset(struct sock *sk); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 3361ae9..7aa51eb 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -555,7 +555,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) return rc; } -int llc_wait_data(struct sock *sk, long timeo) +static int llc_wait_data(struct sock *sk, long timeo) { int rc; @@ -1003,9 +1003,6 @@ static struct proto_ops llc_ui_ops = { .sendpage = sock_no_sendpage, }; -extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); -extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); - static char llc_proc_err_msg[] __initdata = KERN_CRIT "LLC: Unable to register the proc_fs entries\n"; static char llc_sysctl_err_msg[] __initdata = diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 05236c2..8f7b46d 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -1321,7 +1321,7 @@ int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb) return 0; } -int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) +static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb) { llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128; return 0; diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index ab9e6d7..76f94e0 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -819,7 +819,8 @@ static void llc_sk_init(struct sock* sk) * Allocates a LLC sock and initializes it. Returns the new LLC sock * or %NULL if there's no memory available for one */ -struct sock *llc_sk_alloc(int family, int priority, struct proto *prot) +struct sock *llc_sk_alloc(int family, unsigned int __nocast priority, + struct proto *prot) { struct sock *sk = sk_alloc(family, priority, prot, 1); diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 9ccff12..ab0fcd3 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -69,7 +69,7 @@ static void llc_del_sap(struct llc_sap *sap) write_unlock_bh(&llc_sap_list_lock); } -struct llc_sap *__llc_sap_find(unsigned char sap_value) +static struct llc_sap *__llc_sap_find(unsigned char sap_value) { struct llc_sap* sap; diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c index 4d99d2f..d1eaddb 100644 --- a/net/llc/sysctl_net_llc.c +++ b/net/llc/sysctl_net_llc.c @@ -8,17 +8,12 @@ #include #include #include +#include #ifndef CONFIG_SYSCTL #error This file should not be compiled without CONFIG_SYSCTL defined #endif -extern int sysctl_llc2_ack_timeout; -extern int sysctl_llc2_busy_timeout; -extern int sysctl_llc2_p_timeout; -extern int sysctl_llc2_rej_timeout; -extern int sysctl_llc_station_ack_timeout; - static struct ctl_table llc2_timeout_table[] = { { .ctl_name = NET_LLC2_ACK_TIMEOUT, -- cgit v0.10.2 From d389424e00f9097cd24b3df4ca0ab7221f140eeb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 07:57:21 -0300 Subject: [LLC]: Fix the accept path Borrowing the structure of TCP/IP for this. On the receive of new connections I was bh_lock_socking the _new_ sock, not the listening one, duh, now it survives the ssh connections storm I've been using to test this specific bug. Also fixes send side skb sock accounting. Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h index 9dcfcf4..2c56dbe 100644 --- a/include/net/llc_sap.h +++ b/include/net/llc_sap.h @@ -19,7 +19,8 @@ struct sock; extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, unsigned char prim); -extern struct sk_buff *llc_alloc_frame(struct net_device *dev); +extern struct sk_buff *llc_alloc_frame(struct sock *sk, + struct net_device *dev); extern void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 8f7b46d..b0bcfb1 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -60,24 +60,10 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) { - int rc = -ENOTCONN; - u8 dsap; - struct llc_sap *sap; - - llc_pdu_decode_dsap(skb, &dsap); - sap = llc_sap_find(dsap); - if (sap) { - struct llc_conn_state_ev *ev = llc_conn_ev(skb); - struct llc_sock *llc = llc_sk(sk); + struct llc_conn_state_ev *ev = llc_conn_ev(skb); - llc_pdu_decode_sa(skb, llc->daddr.mac); - llc_pdu_decode_da(skb, llc->laddr.mac); - llc->dev = skb->dev; - ev->ind_prim = LLC_CONN_PRIM; - rc = 0; - llc_sap_put(sap); - } - return rc; + ev->ind_prim = LLC_CONN_PRIM; + return 0; } int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) @@ -213,7 +199,7 @@ int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -238,7 +224,7 @@ int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -264,7 +250,7 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -297,7 +283,7 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) llc_pdu_decode_pf_bit(skb, &f_bit); else f_bit = 0; - nskb = llc_alloc_frame(llc->dev); + nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -321,7 +307,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -351,7 +337,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(sk); llc_pdu_decode_pf_bit(skb, &f_bit); - nskb = llc_alloc_frame(llc->dev); + nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); @@ -439,7 +425,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -474,7 +460,7 @@ int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -498,7 +484,7 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -522,7 +508,7 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -546,7 +532,7 @@ int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -570,7 +556,7 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -594,7 +580,7 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -630,7 +616,7 @@ int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -654,7 +640,7 @@ int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -678,7 +664,7 @@ int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -703,7 +689,7 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -727,7 +713,7 @@ int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -751,7 +737,7 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -785,7 +771,7 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; @@ -814,7 +800,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) u8 f_bit; int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); llc_pdu_decode_pf_bit(skb, &f_bit); if (nskb) { @@ -970,7 +956,7 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); if (nskb) { struct llc_sap *sap = llc->sap; diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 76f94e0..e10ce5a 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -58,7 +58,7 @@ int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ; int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) { int rc; - struct llc_sock *llc = llc_sk(sk); + struct llc_sock *llc = llc_sk(skb->sk); struct llc_conn_state_ev *ev = llc_conn_ev(skb); /* @@ -68,7 +68,10 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) */ skb_get(skb); ev->ind_prim = ev->cfm_prim = 0; - rc = llc_conn_service(sk, skb); /* sending event to state machine */ + /* + * Send event to state machine + */ + rc = llc_conn_service(skb->sk, skb); if (unlikely(rc != 0)) { printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__); goto out_kfree_skb; @@ -100,18 +103,14 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) kfree_skb(skb); } break; - case LLC_CONN_PRIM: { - struct sock *parent = skb->sk; - - skb_orphan(skb); + case LLC_CONN_PRIM: /* - * Set the skb->sk to the new struct sock, so that at accept - * type the upper layer can get the newly created struct sock. + * Can't be sock_queue_rcv_skb, because we have to leave the + * skb->sk pointing to the newly created struct sock in + * llc_conn_handler. -acme */ - skb->sk = sk; - skb_queue_tail(&parent->sk_receive_queue, skb); - sk->sk_state_change(parent); - } + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_state_change(sk); break; case LLC_DISC_PRIM: sock_hold(sk); @@ -475,7 +474,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk, } /** - * llc_lookup_established - Finds connection for the remote/local sap/mac + * __llc_lookup_established - Finds connection for the remote/local sap/mac * @sap: SAP * @daddr: address of remote LLC (MAC + SAP) * @laddr: address of local LLC (MAC + SAP) @@ -483,14 +482,16 @@ static int llc_exec_conn_trans_actions(struct sock *sk, * Search connection list of the SAP and finds connection using the remote * mac, remote sap, local mac, and local sap. Returns pointer for * connection found, %NULL otherwise. + * Caller has to make sure local_bh is disabled. */ -struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, - struct llc_addr *laddr) +static struct sock *__llc_lookup_established(struct llc_sap *sap, + struct llc_addr *daddr, + struct llc_addr *laddr) { struct sock *rc; struct hlist_node *node; - read_lock_bh(&sap->sk_list.lock); + read_lock(&sap->sk_list.lock); sk_for_each(rc, node, &sap->sk_list.list) { struct llc_sock *llc = llc_sk(rc); @@ -504,10 +505,22 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, } rc = NULL; found: - read_unlock_bh(&sap->sk_list.lock); + read_unlock(&sap->sk_list.lock); return rc; } +struct sock *llc_lookup_established(struct llc_sap *sap, + struct llc_addr *daddr, + struct llc_addr *laddr) +{ + struct sock *sk; + + local_bh_disable(); + sk = __llc_lookup_established(sap, daddr, laddr); + local_bh_enable(); + return sk; +} + /** * llc_lookup_listener - Finds listener for local MAC + SAP * @sap: SAP @@ -516,6 +529,7 @@ found: * Search connection list of the SAP and finds connection listening on * local mac, and local sap. Returns pointer for parent socket found, * %NULL otherwise. + * Caller has to make sure local_bh is disabled. */ static struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr) @@ -523,7 +537,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap, struct sock *rc; struct hlist_node *node; - read_lock_bh(&sap->sk_list.lock); + read_lock(&sap->sk_list.lock); sk_for_each(rc, node, &sap->sk_list.list) { struct llc_sock *llc = llc_sk(rc); @@ -537,10 +551,19 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap, } rc = NULL; found: - read_unlock_bh(&sap->sk_list.lock); + read_unlock(&sap->sk_list.lock); return rc; } +static struct sock *__llc_lookup(struct llc_sap *sap, + struct llc_addr *daddr, + struct llc_addr *laddr) +{ + struct sock *sk = __llc_lookup_established(sap, daddr, laddr); + + return sk ? : llc_lookup_listener(sap, laddr); +} + /** * llc_data_accept_state - designates if in this state data can be sent. * @state: state of connection. @@ -666,15 +689,34 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb) { struct llc_conn_state_ev *ev = llc_conn_ev(skb); - struct llc_sock *llc = llc_sk(sk); - if (!llc->dev) - llc->dev = skb->dev; ev->type = LLC_CONN_EV_TYPE_PDU; ev->reason = 0; return llc_conn_state_process(sk, skb); } +static struct sock *llc_create_incoming_sock(struct sock *sk, + struct net_device *dev, + struct llc_addr *saddr, + struct llc_addr *daddr) +{ + struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC, + sk->sk_prot); + struct llc_sock *newllc, *llc = llc_sk(sk); + + if (!newsk) + goto out; + newllc = llc_sk(newsk); + memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr)); + memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr)); + newllc->dev = dev; + dev_hold(dev); + llc_sap_add_socket(llc->sap, newsk); + llc_sap_hold(llc->sap); +out: + return newsk; +} + void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) { struct llc_addr saddr, daddr; @@ -685,34 +727,35 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_da(skb, daddr.mac); llc_pdu_decode_dsap(skb, &daddr.lsap); - sk = llc_lookup_established(sap, &saddr, &daddr); - if (!sk) { + sk = __llc_lookup(sap, &saddr, &daddr); + if (!sk) + goto drop; + + bh_lock_sock(sk); + /* + * This has to be done here and not at the upper layer ->accept + * method because of the way the PROCOM state machine works: + * it needs to set several state variables (see, for instance, + * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to + * the originator of the new connection, and this state has to be + * in the newly created struct sock private area. -acme + */ + if (unlikely(sk->sk_state == TCP_LISTEN)) { + struct sock *newsk = llc_create_incoming_sock(sk, skb->dev, + &saddr, &daddr); + if (!newsk) + goto drop_unlock; + skb_set_owner_r(skb, newsk); + } else { /* - * Didn't find an active connection; verify if there - * is a listening socket for this llc addr + * Can't be skb_set_owner_r, this will be done at the + * llc_conn_state_process function, later on, when we will use + * skb_queue_rcv_skb to send it to upper layers, this is + * another trick required to cope with how the PROCOM state + * machine works. -acme */ - struct llc_sock *llc; - struct sock *parent = llc_lookup_listener(sap, &daddr); - - if (!parent) { - dprintk("llc_lookup_listener failed!\n"); - goto drop; - } - - sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot); - if (!sk) { - sock_put(parent); - goto drop; - } - llc = llc_sk(sk); - memcpy(&llc->laddr, &daddr, sizeof(llc->laddr)); - memcpy(&llc->daddr, &saddr, sizeof(llc->daddr)); - llc_sap_add_socket(sap, sk); - sock_hold(sk); - skb_set_owner_r(skb, parent); - sock_put(parent); + skb->sk = sk; } - bh_lock_sock(sk); if (!sock_owned_by_user(sk)) llc_conn_rcv(sk, skb); else { @@ -720,11 +763,16 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) llc_set_backlog_type(skb, LLC_PACKET); sk_add_backlog(sk, skb); } +out: bh_unlock_sock(sk); sock_put(sk); return; drop: kfree_skb(skb); + return; +drop_unlock: + kfree_skb(skb); + goto out; } #undef LLC_REFCNT_DEBUG diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c index 764dbd7..ba90f7f 100644 --- a/net/llc/llc_if.c +++ b/net/llc/llc_if.c @@ -107,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap) ev->type = LLC_CONN_EV_TYPE_PRIM; ev->prim = LLC_CONN_PRIM; ev->prim_type = LLC_PRIM_TYPE_REQ; + skb_set_owner_w(skb, sk); rc = llc_conn_state_process(sk, skb); } out_put: @@ -141,6 +142,7 @@ int llc_send_disc(struct sock *sk) skb = alloc_skb(0, GFP_ATOMIC); if (!skb) goto out; + skb_set_owner_w(skb, sk); sk->sk_state = TCP_CLOSING; ev = llc_conn_ev(skb); ev->type = LLC_CONN_EV_TYPE_PRIM; diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index 6acdebf..bb3580f 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -103,7 +103,7 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(skb->dev); + nskb = llc_alloc_frame(NULL, skb->dev); if (!nskb) goto out; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, @@ -148,7 +148,7 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(skb->dev); + nskb = llc_alloc_frame(NULL, skb->dev); if (!nskb) goto out; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 9f064b3..e6d5389 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -31,7 +31,7 @@ * Allocates an sk_buff for frame and initializes sk_buff fields. * Returns allocated skb or %NULL when out of memory. */ -struct sk_buff *llc_alloc_frame(struct net_device *dev) +struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) { struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); @@ -41,6 +41,8 @@ struct sk_buff *llc_alloc_frame(struct net_device *dev) skb->protocol = htons(ETH_P_802_2); skb->dev = dev; skb->mac.raw = skb->head; + if (sk != NULL) + skb_set_owner_w(skb, sk); } return skb; } diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index ec4693f..f37dbf8 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -254,7 +254,7 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) { int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(skb->dev); + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); if (!nskb) goto out; @@ -275,7 +275,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff* nskb = llc_alloc_frame(skb->dev); + struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev); if (!nskb) goto out; @@ -299,7 +299,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(skb->dev); + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); if (!nskb) goto out; -- cgit v0.10.2 From 8420e1b541fe92aee1d8d4d25d9e33eaca756a7b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 22 Sep 2005 08:29:08 -0300 Subject: [LLC]: fix llc_ui_recvmsg, making it behave like tcp_recvmsg In fact it is an exact copy of the parts that makes sense to LLC :-) Signed-off-by: Arnaldo Carvalho de Melo diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index e44f494..54852ff 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -38,6 +38,7 @@ struct llc_sock { struct llc_addr laddr; /* lsap/mac pair */ struct llc_addr daddr; /* dsap/mac pair */ struct net_device *dev; /* device to send to remote */ + u32 copied_seq; /* head of yet unread data */ u8 retry_count; /* number of retries */ u8 ack_must_be_send; u8 first_pdu_Ns; diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 7aa51eb..59d02cb 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -648,53 +648,167 @@ out: * llc_ui_recvmsg - copy received data to the socket user. * @sock: Socket to copy data from. * @msg: Various user space related information. - * @size: Size of user buffer. + * @len: Size of user buffer. * @flags: User specified flags. * * Copy received data to the socket user. * Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t size, int flags) + struct msghdr *msg, size_t len, int flags) { - struct sock *sk = sock->sk; struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; - struct sk_buff *skb; + const int nonblock = flags & MSG_DONTWAIT; + struct sk_buff *skb = NULL; + struct sock *sk = sock->sk; + struct llc_sock *llc = llc_sk(sk); size_t copied = 0; - int rc = -ENOMEM; - int noblock = flags & MSG_DONTWAIT; + u32 peek_seq = 0; + u32 *seq; + unsigned long used; + int target; /* Read at least this many bytes */ + long timeo; - dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__, - llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); lock_sock(sk); - if (skb_queue_empty(&sk->sk_receive_queue)) { - rc = llc_wait_data(sk, sock_rcvtimeo(sk, noblock)); - if (rc) - goto out; - } - skb = skb_dequeue(&sk->sk_receive_queue); - if (!skb) /* shutdown */ + copied = -ENOTCONN; + if (sk->sk_state == TCP_LISTEN) goto out; - copied = skb->len; - if (copied > size) - copied = size; - rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (rc) - goto dgram_free; - if (skb->len > copied) { - skb_pull(skb, copied); - skb_queue_head(&sk->sk_receive_queue, skb); - } - if (uaddr) - memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); - msg->msg_namelen = sizeof(*uaddr); - if (!skb->next) { -dgram_free: - kfree_skb(skb); - } + + timeo = sock_rcvtimeo(sk, nonblock); + + seq = &llc->copied_seq; + if (flags & MSG_PEEK) { + peek_seq = llc->copied_seq; + seq = &peek_seq; + } + + target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); + copied = 0; + + do { + u32 offset; + + /* + * We need to check signals first, to get correct SIGURG + * handling. FIXME: Need to check this doesn't impact 1003.1g + * and move it down to the bottom of the loop + */ + if (signal_pending(current)) { + if (copied) + break; + copied = timeo ? sock_intr_errno(timeo) : -EAGAIN; + break; + } + + /* Next get a buffer. */ + + skb = skb_peek(&sk->sk_receive_queue); + if (skb) { + offset = *seq; + goto found_ok_skb; + } + /* Well, if we have backlog, try to process it now yet. */ + + if (copied >= target && !sk->sk_backlog.tail) + break; + + if (copied) { + if (sk->sk_err || + sk->sk_state == TCP_CLOSE || + (sk->sk_shutdown & RCV_SHUTDOWN) || + !timeo || + (flags & MSG_PEEK)) + break; + } else { + if (sock_flag(sk, SOCK_DONE)) + break; + + if (sk->sk_err) { + copied = sock_error(sk); + break; + } + if (sk->sk_shutdown & RCV_SHUTDOWN) + break; + + if (sk->sk_state == TCP_CLOSE) { + if (!sock_flag(sk, SOCK_DONE)) { + /* + * This occurs when user tries to read + * from never connected socket. + */ + copied = -ENOTCONN; + break; + } + break; + } + if (!timeo) { + copied = -EAGAIN; + break; + } + } + + if (copied >= target) { /* Do not sleep, just process backlog. */ + release_sock(sk); + lock_sock(sk); + } else + sk_wait_data(sk, &timeo); + + if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) { + if (net_ratelimit()) + printk(KERN_DEBUG "LLC(%s:%d): Application " + "bug, race in MSG_PEEK.\n", + current->comm, current->pid); + peek_seq = llc->copied_seq; + } + continue; + found_ok_skb: + /* Ok so how much can we use? */ + used = skb->len - offset; + if (len < used) + used = len; + + if (!(flags & MSG_TRUNC)) { + int rc = skb_copy_datagram_iovec(skb, offset, + msg->msg_iov, used); + if (rc) { + /* Exception. Bailout! */ + if (!copied) + copied = -EFAULT; + break; + } + } + + *seq += used; + copied += used; + len -= used; + + if (used + offset < skb->len) + continue; + + if (!(flags & MSG_PEEK)) { + sk_eat_skb(sk, skb); + *seq = 0; + } + } while (len > 0); + + /* + * According to UNIX98, msg_name/msg_namelen are ignored + * on connected socket. -ANK + * But... af_llc still doesn't have separate sets of methods for + * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will + * eventually fix this tho :-) -acme + */ + if (sk->sk_type == SOCK_DGRAM) + goto copy_uaddr; out: release_sock(sk); - return rc ? : copied; + return copied; +copy_uaddr: + if (uaddr != NULL && skb != NULL) { + memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); + msg->msg_namelen = sizeof(*uaddr); + } + goto out; } /** diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index e10ce5a..042b24a 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -120,8 +120,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) sk->sk_socket->state = SS_UNCONNECTED; sk->sk_state = TCP_CLOSE; if (!sock_flag(sk, SOCK_DEAD)) { - sk->sk_state_change(sk); sock_set_flag(sk, SOCK_DEAD); + sk->sk_state_change(sk); } } kfree_skb(skb); diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 36e8db3..bd531cb 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) llc_ui_format_mac(seq, llc->daddr.mac); seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap, atomic_read(&sk->sk_wmem_alloc), - atomic_read(&sk->sk_rmem_alloc), + atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq, sk->sk_state, sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, llc->link); diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index e6d5389..4029cee 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -49,9 +49,12 @@ struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) { - struct sockaddr_llc *addr = llc_ui_skb_cb(skb); + struct sockaddr_llc *addr; + if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */ + return; /* save primitive for use by the user. */ + addr = llc_ui_skb_cb(skb); addr->sllc_family = sk->sk_family; addr->sllc_arphrd = skb->dev->type; addr->sllc_test = prim == LLC_TEST_PRIM; -- cgit v0.10.2 From 91fbc6edfa7086b5fcdb74ea82ab747104541f1f Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 22 Sep 2005 13:26:44 +0100 Subject: NTFS: Fix sparse warnings that have crept in over time. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index c7e9237..ee8665f 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -22,6 +22,10 @@ ToDo/Notes: - Enable the code for setting the NT4 compatibility flag when we start making NTFS 1.2 specific modifications. +2.1.25-WIP + + - Fix sparse warnings that have crept in over time. + 2.1.24 - Lots of bug fixes and support more clean journal states. - Support journals ($LogFile) which have been modified by chkdsk. This diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 609ad17..dbf5c2a 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -317,12 +317,13 @@ typedef u64 MFT_REF; typedef le64 leMFT_REF; #define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \ - ((MFT_REF)(m) & MFT_REF_MASK_CPU))) + ((MFT_REF)(m) & (u64)MFT_REF_MASK_CPU))) #define MK_LE_MREF(m, s) cpu_to_le64(MK_MREF(m, s)) -#define MREF(x) ((unsigned long)((x) & MFT_REF_MASK_CPU)) +#define MREF(x) ((unsigned long)((x) & (u64)MFT_REF_MASK_CPU)) #define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff)) -#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & MFT_REF_MASK_CPU)) +#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & \ + (u64)MFT_REF_MASK_CPU)) #define MSEQNO_LE(x) ((u16)((le64_to_cpu(x) >> 48) & 0xffff)) #define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0) diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index 42388f9..a51f3dd 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h @@ -113,7 +113,7 @@ typedef struct { */ enum { RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), - RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ + RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ } __attribute__ ((__packed__)); typedef le16 RESTART_AREA_FLAGS; -- cgit v0.10.2 From 4c898c7f2f286b204fefc5dddb568f755d195d0c Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Thu, 22 Sep 2005 00:47:11 -0700 Subject: [PATCH] Driver Core: fis bus rescan devices race bus_rescan_devices_helper() does not hold the dev->sem when it checks for !dev->driver(). device_attach() holds the sem, but calls again device_bind_driver() even when dev->driver is set. What happens is that a first device_attach() call (module insertion time) is on the way binding the device to a driver. Another thread calls bus_rescan_devices(). Now when bus_rescan_devices_helper() checks for dev->driver it is still NULL 'cos the the prior device_attach() is not yet finished. But as soon as the first one releases the dev->sem the second device_attach() tries to rebind the already bound device again. device_bind_driver() does this blindly which leads to a corrupt driver->klist_devices list (the device links itself, the head points to the device). Later a call to device_release_driver() sets dev->driver to NULL and breaks the link it has to itself on knode_driver. Rmmoding the driver later calls driver_detach() which leads to an endless loop 'cos the list head in klist_devices still points to the device. And since dev->driver is NULL it's stuck with the same device forever. Boom. And rmmod hangs. Very easy to reproduce with new-style pcmcia and a 16bit card. Just loop modprobe ;cardctl eject; rmmod . Easiest fix is to check if the device is already bound to a driver in device_bind_driver(). This avoids the double binding. Signed-off-by: Daniel Ritz Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/base/dd.c b/drivers/base/dd.c index d5bbce3..3565e97 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -40,6 +40,9 @@ */ void device_bind_driver(struct device * dev) { + if (klist_node_attached(&dev->knode_driver)) + return; + pr_debug("bound device '%s' to driver '%s'\n", dev->bus_id, dev->driver->name); klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); -- cgit v0.10.2 From d305ef5d2a4e77bfa66160513f4a7494126a506b Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Thu, 22 Sep 2005 00:47:24 -0700 Subject: [PATCH] driver core: add helper device_is_registered() add the helper and use it instead of open coding the klist_node_attached() check (which is a layering violation IMHO) idea by Alan Stern. Signed-off-by: Daniel Ritz Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 91ea8e4..dbb3eb0 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -437,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) if (cdev->dev.driver_data) { gdev = (struct ccwgroup_device *)cdev->dev.driver_data; if (get_device(&gdev->dev)) { - if (klist_node_attached(&gdev->dev.knode_bus)) + if (device_is_registered(&gdev->dev)) return gdev; put_device(&gdev->dev); } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c47c8052..f1fb67f 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -987,7 +987,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) /* remove this interface if it has been registered */ interface = dev->actconfig->interface[i]; - if (!klist_node_attached(&interface->dev.knode_bus)) + if (!device_is_registered(&interface->dev)) continue; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 087af73..7d13150 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -303,7 +303,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() */ - if (klist_node_attached(&dev->knode_bus)) + if (device_is_registered(dev)) device_bind_driver(dev); return 0; @@ -336,8 +336,8 @@ void usb_driver_release_interface(struct usb_driver *driver, if (iface->condition != USB_INTERFACE_BOUND) return; - /* release only after device_add() */ - if (klist_node_attached(&dev->knode_bus)) { + /* don't release if the interface hasn't been added yet */ + if (device_is_registered(dev)) { iface->condition = USB_INTERFACE_UNBINDING; device_release_driver(dev); } diff --git a/include/linux/device.h b/include/linux/device.h index 06e5d42..95d607a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -317,6 +317,11 @@ dev_set_drvdata (struct device *dev, void *data) dev->driver_data = data; } +static inline int device_is_registered(struct device *dev) +{ + return klist_node_attached(&dev->knode_bus); +} + /* * High level routines for use by the bus drivers */ -- cgit v0.10.2 From 3e51377dc412df9d4933c4fd1a147b5b560abe10 Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Thu, 22 Sep 2005 00:47:36 -0700 Subject: [PATCH] fix class symlinks in sysfs The class symlinks in sysfs don't properly handle changing device names. To demonstrate, rename your network device from eth0 to eth1. Your pci (or usb, or whatever) device will still have a 'net:eth0' link, except now it points to /sys/class/net/eth1. The attached patch makes sure the class symlink name changes when the class device name changes. It isn't 100% correct, it should be using sysfs_rename_link. Unfortunately, sysfs_rename_link doesn't exist. Signed-off-by: Bill Nottingham Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/base/class.c b/drivers/base/class.c index 3b112e3..ce23dc8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -669,6 +669,7 @@ void class_device_destroy(struct class *cls, dev_t devt) int class_device_rename(struct class_device *class_dev, char *new_name) { int error = 0; + char *old_class_name = NULL, *new_class_name = NULL; class_dev = class_device_get(class_dev); if (!class_dev) @@ -677,12 +678,24 @@ int class_device_rename(struct class_device *class_dev, char *new_name) pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, new_name); + if (class_dev->dev) + old_class_name = make_class_name(class_dev); + strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); + if (class_dev->dev) { + new_class_name = make_class_name(class_dev); + sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + new_class_name); + sysfs_remove_link(&class_dev->dev->kobj, old_class_name); + } class_device_put(class_dev); + kfree(old_class_name); + kfree(new_class_name); + return error; } -- cgit v0.10.2 From dba28010b27ab56d2c4cec5f361e0947295addfd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Sep 2005 00:47:46 -0700 Subject: [PATCH] I2C: remove me from the MAINTAINERS file for i2c Remove my name from the I2C maintainer, Jean is more than capable of handling it all now. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index ade7415..78aca12 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1063,8 +1063,6 @@ M: wli@holomorphy.com S: Maintained I2C SUBSYSTEM -P: Greg Kroah-Hartman -M: greg@kroah.com P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org -- cgit v0.10.2 From 1029d6b58adc3225911c56af26895871dd2ea8cf Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 22 Sep 2005 00:48:02 -0700 Subject: [PATCH] PCI: remove unused "scratch" Unused variable. Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 1044498..e1743be 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -7,7 +7,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct pci_dev *pdev; - char *scratch; int i = 0; int length = 0; @@ -18,9 +17,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, if (!pdev) return -ENODEV; - scratch = buffer; - - if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length, "PCI_CLASS=%04X", pdev->class)) -- cgit v0.10.2 From 656da9da3745abcbbbdca598745d04c6de2c8843 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 22 Sep 2005 00:48:11 -0700 Subject: [PATCH] PCI: convert kcalloc to kzalloc This patch converts kcalloc(1, ...) calls to use the new kzalloc() function. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index b140944..a32ae82 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -159,7 +159,7 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); - slot = kcalloc(1, sizeof(*slot), GFP_KERNEL); + slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; bss_hotplug_slot->private = slot; @@ -491,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) if (sn_pci_slot_valid(pci_bus, device) != 1) continue; - bss_hotplug_slot = kcalloc(1, sizeof(*bss_hotplug_slot), + bss_hotplug_slot = kzalloc(sizeof(*bss_hotplug_slot), GFP_KERNEL); if (!bss_hotplug_slot) { rc = -ENOMEM; @@ -499,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) } bss_hotplug_slot->info = - kcalloc(1, sizeof(struct hotplug_slot_info), + kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!bss_hotplug_slot->info) { rc = -ENOMEM; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 56a3b39..2898830 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -360,7 +360,7 @@ pci_create_resource_files(struct pci_dev *pdev) continue; /* allocate attribute structure, piggyback attribute name */ - res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC); + res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC); if (res_attr) { char *res_attr_name = (char *)(res_attr + 1); -- cgit v0.10.2 From 3c6de9295d28a4fc868b2c09f23e318e3e7b9b6b Mon Sep 17 00:00:00 2001 From: Amos Waterland Date: Thu, 22 Sep 2005 00:48:19 -0700 Subject: [PATCH] fix drivers/pci/probe.c warning This function expects an unsigned 32-bit type as its third argument: static u32 pci_size(u32 base, u32 maxbase, u32 mask) However, given these definitions: #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) #define PCI_ROM_ADDRESS_MASK (~0x7ffUL) these two calls in drivers/pci/probe.c are problematic for architectures for which a UL is not equivalent to a u32: sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK); sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); Hence the below compile warning when building for ARCH=ppc64: drivers/pci/probe.c: In function `pci_read_bases': /.../probe.c:168: warning: large integer implicitly truncated to unsigned type /.../probe.c:218: warning: large integer implicitly truncated to unsigned type Here is a simple fix. Signed-off-by: Amos Waterland Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 26a55d0..c77d5b1 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -165,7 +165,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) if (l == 0xffffffff) l = 0; if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { - sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK); + sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); if (!sz) continue; res->start = l & PCI_BASE_ADDRESS_MEM_MASK; @@ -215,7 +215,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) if (l == 0xffffffff) l = 0; if (sz && sz != 0xffffffff) { - sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); + sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK); if (sz) { res->flags = (l & IORESOURCE_ROM_ENABLE) | IORESOURCE_MEM | IORESOURCE_PREFETCH | -- cgit v0.10.2 From 02fe75a9ad797b4f8ccf1ee8e49833b77cc30c6a Mon Sep 17 00:00:00 2001 From: Linda Xie Date: Thu, 22 Sep 2005 00:48:24 -0700 Subject: [PATCH] PCI Hotplug: Fix buffer overrun in rpadlpar_sysfs.c Signed-off-by: Linda Xie Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index 752e651..db69be8 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -62,7 +62,7 @@ static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr, char drc_name[MAX_DRC_NAME_LEN]; char *end; - if (nbytes > MAX_DRC_NAME_LEN) + if (nbytes >= MAX_DRC_NAME_LEN) return 0; memcpy(drc_name, buf, nbytes); @@ -83,7 +83,7 @@ static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr, char drc_name[MAX_DRC_NAME_LEN]; char *end; - if (nbytes > MAX_DRC_NAME_LEN) + if (nbytes >= MAX_DRC_NAME_LEN) return 0; memcpy(drc_name, buf, nbytes); -- cgit v0.10.2 From 64bd84538ac7f8ba3080eda4d92c66a8441cc6cc Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 22 Sep 2005 00:48:29 -0700 Subject: [PATCH] ub: fix burning cds This patch fixes a few problems with ub and cleans up a couple of things: - Bump UB_MAX_REQ_SG, this allows to burn CDs - Drop initialization of urb.transfer_flags, now that URB_UNLINK_ASYNC is gone - Add forgotten processing of stalls at GetMaxLUN - Remove a few more P3-tagged printks whose time has come - Correct comment about ZIP-100 Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds drivers/block/ub.c | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index aa0bf7e..dfe3581 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -172,7 +172,7 @@ struct bulk_cs_wrap { */ struct ub_dev; -#define UB_MAX_REQ_SG 4 +#define UB_MAX_REQ_SG 9 /* cdrecord requires 32KB and maybe a header */ #define UB_MAX_SECTORS 64 /* @@ -387,7 +387,7 @@ struct ub_dev { struct bulk_cs_wrap work_bcs; struct usb_ctrlrequest work_cr; - int sg_stat[UB_MAX_REQ_SG+1]; + int sg_stat[6]; struct ub_scsi_trace tr; }; @@ -525,12 +525,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, "qlen %d qmax %d\n", sc->cmd_queue.qlen, sc->cmd_queue.qmax); cnt += sprintf(page + cnt, - "sg %d %d %d %d %d\n", + "sg %d %d %d %d %d .. %d\n", sc->sg_stat[0], sc->sg_stat[1], sc->sg_stat[2], sc->sg_stat[3], - sc->sg_stat[4]); + sc->sg_stat[4], + sc->sg_stat[5]); list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); @@ -835,7 +836,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, return -1; } cmd->nsg = n_elem; - sc->sg_stat[n_elem]++; + sc->sg_stat[n_elem < 5 ? n_elem : 5]++; /* * build the command @@ -891,7 +892,7 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, return -1; } cmd->nsg = n_elem; - sc->sg_stat[n_elem]++; + sc->sg_stat[n_elem < 5 ? n_elem : 5]++; memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; @@ -1010,7 +1011,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->send_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); - sc->work_urb.transfer_flags = 0; /* Fill what we shouldn't be filling, because usb-storage did so. */ sc->work_urb.actual_length = 0; @@ -1019,7 +1019,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ - printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); return rc; } @@ -1190,11 +1189,9 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) return; } if (urb->status != 0) { - printk("ub: cmd #%d cmd status (%d)\n", cmd->tag, urb->status); /* P3 */ goto Bad_End; } if (urb->actual_length != US_BULK_CB_WRAP_LEN) { - printk("ub: cmd #%d xferred %d\n", cmd->tag, urb->actual_length); /* P3 */ /* XXX Must do reset here to unconfuse the device */ goto Bad_End; } @@ -1395,14 +1392,12 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, page_address(sg->page) + sg->offset, sg->length, ub_urb_complete, sc); - sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ - printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; @@ -1442,7 +1437,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->recv_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); - sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; @@ -1563,7 +1557,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_urb_complete, sc); - sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; @@ -2000,17 +1993,16 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe, (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl); - sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { if (rc == -EPIPE) { - printk("%s: Stall at GetMaxLUN, using 1 LUN\n", + printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n", sc->name); /* P3 */ } else { - printk(KERN_WARNING + printk(KERN_NOTICE "%s: Unable to submit GetMaxLUN (%d)\n", sc->name, rc); } @@ -2028,6 +2020,18 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) del_timer_sync(&timer); usb_kill_urb(&sc->work_urb); + if ((rc = sc->work_urb.status) < 0) { + if (rc == -EPIPE) { + printk("%s: Stall at GetMaxLUN, using 1 LUN\n", + sc->name); /* P3 */ + } else { + printk(KERN_NOTICE + "%s: Error at GetMaxLUN (%d)\n", + sc->name, rc); + } + goto err_io; + } + if (sc->work_urb.actual_length != 1) { printk("%s: GetMaxLUN returned %d bytes\n", sc->name, sc->work_urb.actual_length); /* P3 */ @@ -2048,6 +2052,7 @@ static int ub_sync_getmaxlun(struct ub_dev *sc) kfree(p); return nluns; +err_io: err_submit: kfree(p); err_alloc: @@ -2080,7 +2085,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); - sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; @@ -2241,10 +2245,10 @@ static int ub_probe(struct usb_interface *intf, for (i = 0; i < 3; i++) { if ((rc = ub_sync_getmaxlun(sc)) < 0) { /* - * Some devices (i.e. Iomega Zip100) need this -- - * apparently the bulk pipes get STALLed when the - * GetMaxLUN request is processed. - * XXX I have a ZIP-100, verify it does this. + * This segment is taken from usb-storage. They say + * that ZIP-100 needs this, but my own ZIP-100 works + * fine without this. + * Still, it does not seem to hurt anything. */ if (rc == -EPIPE) { ub_probe_clear_stall(sc, sc->recv_bulk_pipe); @@ -2313,7 +2317,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) disk->first_minor = lun->id * UB_MINORS_PER_MAJOR; disk->fops = &ub_bd_fops; disk->private_data = lun; - disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */ + disk->driverfs_dev = &sc->intf->dev; rc = -ENOMEM; if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL) @@ -2466,9 +2470,6 @@ static int __init ub_init(void) { int rc; - /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n", - sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun)); - if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) goto err_regblkdev; devfs_mk_dir(DEVFS_NAME); -- cgit v0.10.2 From b6137383bda844a433d65e027502df7b20ba45c2 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Thu, 22 Sep 2005 00:48:40 -0700 Subject: [PATCH] USB: more device IDs for Option card driver Added support for HUAWEI E600 and Audiovox AirCard User reports say that these devices work without driver modification. Signed-off-by: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 92d0f92..616bea8 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -25,6 +25,7 @@ 2005-06-20 v0.4.1 add missing braces :-/ killed end-of-line whitespace 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 + 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard Work sponsored by: Sigos GmbH, Germany @@ -71,15 +72,21 @@ static int option_send_setup(struct usb_serial_port *port); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 +#define HUAWEI_VENDOR_ID 0x12D1 +#define AUDIOVOX_VENDOR_ID 0x0F3D #define OPTION_PRODUCT_OLD 0x5000 #define OPTION_PRODUCT_FUSION 0x6000 #define OPTION_PRODUCT_FUSION2 0x6300 +#define HUAWEI_PRODUCT_E600 0x1001 +#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, + { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, + { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { } /* Terminating entry */ }; -- cgit v0.10.2 From 72a755fce0243d4168a6153813a1b533b05a7d72 Mon Sep 17 00:00:00 2001 From: Peter Favrholdt Date: Thu, 22 Sep 2005 00:48:49 -0700 Subject: [PATCH] USB: ftdi_sio: allow baud rate to be changed without raising RTS and DTR I'm using a 2 port USB RS232 dongle to connect to a serial-IR cradle for a bar code reader). Detecting the baudrate of the serial-IR involves keeping DTR low while changing baudrate. This works using normal 16550A serial ports as well as the FTDI driver version 1.4.0 (Linux 2.6.8) but stopped working with the change to "ensure RTS and DTR are raised when changing baudrate" introduced in version 1.4.1 (Linux 2.6.9). The attached patch fixes this, so RTS and DTR is only raised when changing baudrate iff the previous baudrate was B0. Signed-off-by: Peter Favrholdt Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4e434cb..5a8631c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1846,10 +1846,12 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ } else { /* set the baudrate determined before */ if (change_speed(port)) { - err("%s urb failed to set baurdrate", __FUNCTION__); + err("%s urb failed to set baudrate", __FUNCTION__); + } + /* Ensure RTS and DTR are raised when baudrate changed from 0 */ + if ((old_termios->c_cflag & CBAUD) == B0) { + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } - /* Ensure RTS and DTR are raised */ - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* Set flow control */ -- cgit v0.10.2 From 2ba08e825e5a666f540bff15e9977725675e8de6 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Thu, 22 Sep 2005 00:48:58 -0700 Subject: [PATCH] USB: fix pxa2xx_udc compile warnings This patch fixes several types in the PXA25x udc driver and hence fixes several compiler warnings. Signed-off-by: Richard Purdie Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1507738..73f8c94 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -422,7 +422,7 @@ static inline void ep0_idle (struct pxa2xx_udc *dev) } static int -write_packet(volatile u32 *uddr, struct pxa2xx_request *req, unsigned max) +write_packet(volatile unsigned long *uddr, struct pxa2xx_request *req, unsigned max) { u8 *buf; unsigned length, count; @@ -2602,7 +2602,7 @@ static int __exit pxa2xx_udc_remove(struct device *_dev) * VBUS IRQs should probably be ignored so that the PXA device just acts * "dead" to USB hosts until system resume. */ -static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level) +static int pxa2xx_udc_suspend(struct device *dev, pm_message_t state, u32 level) { struct pxa2xx_udc *udc = dev_get_drvdata(dev); diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index d0bc396..a58f3e6 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h @@ -69,11 +69,11 @@ struct pxa2xx_ep { * UDDR = UDC Endpoint Data Register (the fifo) * DRCM = DMA Request Channel Map */ - volatile u32 *reg_udccs; - volatile u32 *reg_ubcr; - volatile u32 *reg_uddr; + volatile unsigned long *reg_udccs; + volatile unsigned long *reg_ubcr; + volatile unsigned long *reg_uddr; #ifdef USE_DMA - volatile u32 *reg_drcmr; + volatile unsigned long *reg_drcmr; #define drcmr(n) .reg_drcmr = & DRCMR ## n , #else #define drcmr(n) -- cgit v0.10.2 From 4b2e790a4d73d729d936cc42f3b08af34f8ea5c6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 22 Sep 2005 00:49:07 -0700 Subject: [PATCH] USB: sl811-hcd minor fixes Three minor sl811-hcd fixes: - Elminate memory leak on one (rare) disable/shutdown path. - For periodic transfers that don't need to be scheduled, update urb->start_frame to represent the transfer phase correctly. - Report the (single) port as removable, by default. Since no drivers yet use start_frame or that part of the hub descriptor, only that leak is likely to ever matter. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds drivers/usb/host/sl811-hcd.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index d2a1fd4..d42a15d 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -782,6 +782,9 @@ retry: /* usb 1.1 says max 90% of a frame is available for periodic transfers. * this driver doesn't promise that much since it's got to handle an * IRQ per packet; irq handling latencies also use up that time. + * + * NOTE: the periodic schedule is a sparse tree, with the load for + * each branch minimized. see fig 3.5 in the OHCI spec for example. */ #define MAX_PERIODIC_LOAD 500 /* out of 1000 usec */ @@ -843,6 +846,7 @@ static int sl811h_urb_enqueue( if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) || !HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; + kfree(ep); goto fail; } @@ -911,8 +915,16 @@ static int sl811h_urb_enqueue( case PIPE_ISOCHRONOUS: case PIPE_INTERRUPT: urb->interval = ep->period; - if (ep->branch < PERIODIC_SIZE) + if (ep->branch < PERIODIC_SIZE) { + /* NOTE: the phase is correct here, but the value + * needs offsetting by the transfer queue depth. + * All current drivers ignore start_frame, so this + * is unlikely to ever matter... + */ + urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1)) + + ep->branch; break; + } retval = balance(sl811, ep->period, ep->load); if (retval < 0) @@ -1122,7 +1134,7 @@ sl811h_hub_descriptor ( desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp); /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ - desc->bitmap[0] = 1 << 1; + desc->bitmap[0] = 0 << 1; desc->bitmap[1] = ~0; } -- cgit v0.10.2 From a85a46f2c38def5150251816890393803fdae7d0 Mon Sep 17 00:00:00 2001 From: Kevin Vigor Date: Thu, 22 Sep 2005 00:49:24 -0700 Subject: [PATCH] USB: fix pegasus driver Addresses some small bugs in the pegasus ethernet-over-USB driver. Specifically, malformed long packets from the adapter could cause a kernel panic; the interrupt interval calculation was inappropriate for high-speed devices; the return code from read_mii_word was tested incorrectly; and failure to unlink outstanding URBs before freeing them could lead to kernel panics when unloading the driver. Signed-off-by: Kevin Vigor Cc: Petko Manolov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 7484d34..6a4ffe6 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -648,6 +648,13 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) } /* + * If the packet is unreasonably long, quietly drop it rather than + * kernel panicing by calling skb_put. + */ + if (pkt_len > PEGASUS_MTU) + goto goon; + + /* * at this point we are sure pegasus->rx_skb != NULL * so we go ahead and pass up the packet. */ @@ -886,15 +893,17 @@ static inline void get_interrupt_interval(pegasus_t * pegasus) __u8 data[2]; read_eprom_word(pegasus, 4, (__u16 *) data); - if (data[1] < 0x80) { - if (netif_msg_timer(pegasus)) - dev_info(&pegasus->intf->dev, - "intr interval changed from %ums to %ums\n", - data[1], 0x80); - data[1] = 0x80; -#ifdef PEGASUS_WRITE_EEPROM - write_eprom_word(pegasus, 4, *(__u16 *) data); + if (pegasus->usb->speed != USB_SPEED_HIGH) { + if (data[1] < 0x80) { + if (netif_msg_timer(pegasus)) + dev_info(&pegasus->intf->dev, "intr interval " + "changed from %ums to %ums\n", + data[1], 0x80); + data[1] = 0x80; +#ifdef PEGASUS_WRITE_EEPROM + write_eprom_word(pegasus, 4, *(__u16 *) data); #endif + } } pegasus->intr_interval = data[1]; } @@ -904,8 +913,9 @@ static void set_carrier(struct net_device *net) pegasus_t *pegasus = netdev_priv(net); u16 tmp; - if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) + if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) return; + if (tmp & BMSR_LSTATUS) netif_carrier_on(net); else @@ -1355,6 +1365,7 @@ static void pegasus_disconnect(struct usb_interface *intf) cancel_delayed_work(&pegasus->carrier_check); unregister_netdev(pegasus->net); usb_put_dev(interface_to_usbdev(intf)); + unlink_all_urbs(pegasus); free_all_urbs(pegasus); free_skb_pool(pegasus); if (pegasus->rx_skb) -- cgit v0.10.2 From b27c73dcab61826e5f1228d69d56f469b0abfc05 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Thu, 22 Sep 2005 00:49:33 -0700 Subject: [PATCH] usb/serial/option.c: Increase input buffer size The card sometimes sends >2000 bytes in one single chunk. Ouch. Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 616bea8..4989e57 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -26,6 +26,8 @@ killed end-of-line whitespace 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard + 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes + wants to send >2000 bytes. Work sponsored by: Sigos GmbH, Germany @@ -139,7 +141,7 @@ static int debug; #define N_IN_URB 4 #define N_OUT_URB 1 -#define IN_BUFLEN 1024 +#define IN_BUFLEN 4096 #define OUT_BUFLEN 128 struct option_port_private { -- cgit v0.10.2 From 3a8c1e2910daaff7590173e9d4ca07153e8a3517 Mon Sep 17 00:00:00 2001 From: David Hollis Date: Thu, 22 Sep 2005 00:49:39 -0700 Subject: [PATCH] USB: Add Novatel CDMA Wireless PC card IDs to airprime USB: Add device id's for Novatel Wireless CDMA wireless PC card. The Novatel CDMA card behaves the same as the AirPrime by providing a USB serial port. Signed-off-by: David Hollis Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index a4ce000..926d4c2 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -16,7 +16,8 @@ #include "usb-serial.h" static struct usb_device_id id_table [] = { - { USB_DEVICE(0xf3d, 0x0112) }, + { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ + { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v0.10.2 From c6c88834b2c6635df9d17695feb50c835bc8efc6 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 22 Sep 2005 00:49:45 -0700 Subject: [PATCH] ub: Comment out unconditional stall clear This code appears to be more trouble than it's worth, considering that no normal users reload drivers. So, we comment it for now. It is not removed outright for the benefit of hackers (that is, myself). Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/block/ub.c b/drivers/block/ub.c index dfe3581..ed4d500 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2217,8 +2217,10 @@ static int ub_probe(struct usb_interface *intf, * This is needed to clear toggles. It is a problem only if we do * `rmmod ub && modprobe ub` without disconnects, but we like that. */ +#if 0 /* iPod Mini fails if we do this (big white iPod works) */ ub_probe_clear_stall(sc, sc->recv_bulk_pipe); ub_probe_clear_stall(sc, sc->send_bulk_pipe); +#endif /* * The way this is used by the startup code is a little specific. -- cgit v0.10.2 From 0fc084eaffe0a9a82a0c94da9ee9f7060ade8b04 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 22 Sep 2005 00:49:51 -0700 Subject: [PATCH] USB: Update Documentation/usb/URB.txt This patch (as564) updates Documentation/usb/URB.txt, bringing it roughly up to the current level. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt index d59b95c..a49e5f2 100644 --- a/Documentation/usb/URB.txt +++ b/Documentation/usb/URB.txt @@ -1,5 +1,6 @@ Revised: 2000-Dec-05. Again: 2002-Jul-06 +Again: 2005-Sep-19 NOTE: @@ -18,8 +19,8 @@ called USB Request Block, or URB for short. and deliver the data and status back. - Execution of an URB is inherently an asynchronous operation, i.e. the - usb_submit_urb(urb) call returns immediately after it has successfully queued - the requested action. + usb_submit_urb(urb) call returns immediately after it has successfully + queued the requested action. - Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time. @@ -94,8 +95,9 @@ To free an URB, use void usb_free_urb(struct urb *urb) -You may not free an urb that you've submitted, but which hasn't yet been -returned to you in a completion callback. +You may free an urb that you've submitted, but which hasn't yet been +returned to you in a completion callback. It will automatically be +deallocated when it is no longer in use. 1.4. What has to be filled in? @@ -145,30 +147,36 @@ to get seamless ISO streaming. 1.6. How to cancel an already running URB? -For an URB which you've submitted, but which hasn't been returned to -your driver by the host controller, call +There are two ways to cancel an URB you've submitted but which hasn't +been returned to your driver yet. For an asynchronous cancel, call int usb_unlink_urb(struct urb *urb) It removes the urb from the internal list and frees all allocated -HW descriptors. The status is changed to reflect unlinking. After -usb_unlink_urb() returns with that status code, you can free the URB -with usb_free_urb(). +HW descriptors. The status is changed to reflect unlinking. Note +that the URB will not normally have finished when usb_unlink_urb() +returns; you must still wait for the completion handler to be called. -There is also an asynchronous unlink mode. To use this, set the -the URB_ASYNC_UNLINK flag in urb->transfer flags before calling -usb_unlink_urb(). When using async unlinking, the URB will not -normally be unlinked when usb_unlink_urb() returns. Instead, wait -for the completion handler to be called. +To cancel an URB synchronously, call + + void usb_kill_urb(struct urb *urb) + +It does everything usb_unlink_urb does, and in addition it waits +until after the URB has been returned and the completion handler +has finished. It also marks the URB as temporarily unusable, so +that if the completion handler or anyone else tries to resubmit it +they will get a -EPERM error. Thus you can be sure that when +usb_kill_urb() returns, the URB is totally idle. 1.7. What about the completion handler? The handler is of the following type: - typedef void (*usb_complete_t)(struct urb *); + typedef void (*usb_complete_t)(struct urb *, struct pt_regs *) -i.e. it gets just the URB that caused the completion call. +I.e., it gets the URB that caused the completion call, plus the +register values at the time of the corresponding interrupt (if any). In the completion handler, you should have a look at urb->status to detect any USB errors. Since the context parameter is included in the URB, you can pass information to the completion handler. @@ -176,17 +184,11 @@ you can pass information to the completion handler. Note that even when an error (or unlink) is reported, data may have been transferred. That's because USB transfers are packetized; it might take sixteen packets to transfer your 1KByte buffer, and ten of them might -have transferred succesfully before the completion is called. +have transferred succesfully before the completion was called. NOTE: ***** WARNING ***** -Don't use urb->dev field in your completion handler; it's cleared -as part of giving urbs back to drivers. (Addressing an issue with -ownership of periodic URBs, which was otherwise ambiguous.) Instead, -use urb->context to hold all the data your driver needs. - -NOTE: ***** WARNING ***** -Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called +NEVER SLEEP IN A COMPLETION HANDLER. These are normally called during hardware interrupt processing. If you can, defer substantial work to a tasklet (bottom half) to keep system latencies low. You'll probably need to use spinlocks to protect data structures you manipulate @@ -229,24 +231,10 @@ ISO data with some other event stream. Interrupt transfers, like isochronous transfers, are periodic, and happen in intervals that are powers of two (1, 2, 4 etc) units. Units are frames for full and low speed devices, and microframes for high speed ones. - -Currently, after you submit one interrupt URB, that urb is owned by the -host controller driver until you cancel it with usb_unlink_urb(). You -may unlink interrupt urbs in their completion handlers, if you need to. - -After a transfer completion is called, the URB is automagically resubmitted. -THIS BEHAVIOR IS EXPECTED TO BE REMOVED!! - -Interrupt transfers may only send (or receive) the "maxpacket" value for -the given interrupt endpoint; if you need more data, you will need to -copy that data out of (or into) another buffer. Similarly, you can't -queue interrupt transfers. -THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!! - -Note that this automagic resubmission model does make it awkward to use -interrupt OUT transfers. The portable solution involves unlinking those -OUT urbs after the data is transferred, and perhaps submitting a final -URB for a short packet. - The usb_submit_urb() call modifies urb->interval to the implemented interval value that is less than or equal to the requested interval value. + +In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically +restarted when they complete. They end when the completion handler is +called, just like other URBs. If you want an interrupt URB to be restarted, +your completion handler must resubmit it. -- cgit v0.10.2 From 3fd07d3bf0077dcc0f5a33d2eb1938ea050da8da Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 21 Sep 2005 23:54:58 -0500 Subject: [PATCH] ppc32: Fix configuration of PCI IO space on MPC85xx platform For platforms that don't have PCI IO at 0 the outbound window registers were not being properly configured. Signed-off-by: Andrew Klossner Signed-off-by: Kumar K. Gala Signed-off-by: Linus Torvalds diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c index b7242f1..832b8bf 100644 --- a/arch/ppc/syslib/ppc85xx_setup.c +++ b/arch/ppc/syslib/ppc85xx_setup.c @@ -184,8 +184,8 @@ mpc85xx_setup_pci1(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1); - /* Setup outboud IO windows @ MPC85XX_PCI1_IO_BASE */ - pci->potar2 = 0x00000000; + /* Setup outbound IO windows @ MPC85XX_PCI1_IO_BASE */ + pci->potar2 = (MPC85XX_PCI1_LOWER_IO >> 12) & 0x000fffff; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ @@ -235,8 +235,8 @@ mpc85xx_setup_pci2(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI2_UPPER_MEM - MPC85XX_PCI2_LOWER_MEM + 1) - 1); - /* Setup outboud IO windows @ MPC85XX_PCI2_IO_BASE */ - pci->potar2 = 0x00000000; + /* Setup outbound IO windows @ MPC85XX_PCI2_IO_BASE */ + pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff;; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ -- cgit v0.10.2 From 83a78d9ba792660418d692fd6737871aefdbff36 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Mon, 19 Sep 2005 09:36:12 +1000 Subject: [IA64] Fix simscsi for new SCSI midlayer The sd driver now uses scsi_execute_req() for almost everything. scsi_execute_req() converts requests into scatterlists. Fix the HP SCSI disk simulator to understand scatterlists for more commands. Without this patch the current kernel will not boot on the simulator (the disks are always detected as having no sectors, and so cannot be mounted). Signed-off-by: Peter Chubb Signed-off-by: Tony Luck diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index 56405db..a18983a 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c @@ -233,6 +233,23 @@ simscsi_readwrite10 (struct scsi_cmnd *sc, int mode) simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512); } +static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) +{ + + int scatterlen = sc->use_sg; + struct scatterlist *slp; + + if (scatterlen == 0) + memcpy(sc->request_buffer, buf, len); + else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) { + unsigned thislen = min(len, slp->length); + + memcpy(page_address(slp->page) + slp->offset, buf, thislen); + slp++; + len -= thislen; + } +} + static int simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) { @@ -240,6 +257,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) char fname[MAX_ROOT_LEN+16]; size_t disk_size; char *buf; + char localbuf[36]; #if DEBUG_SIMSCSI register long sp asm ("sp"); @@ -263,7 +281,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) /* disk doesn't exist... */ break; } - buf = sc->request_buffer; + buf = localbuf; buf[0] = 0; /* magnetic disk */ buf[1] = 0; /* not a removable medium */ buf[2] = 2; /* SCSI-2 compliant device */ @@ -273,6 +291,7 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) buf[6] = 0; /* reserved */ buf[7] = 0; /* various flags */ memcpy(buf + 8, "HP SIMULATED DISK 0.00", 28); + simscsi_fillresult(sc, buf, 36); sc->result = GOOD; break; @@ -304,16 +323,13 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) simscsi_readwrite10(sc, SSC_WRITE); break; - case READ_CAPACITY: if (desc[target_id] < 0 || sc->request_bufflen < 8) { break; } - buf = sc->request_buffer; - + buf = localbuf; disk_size = simscsi_get_disk_size(desc[target_id]); - /* pretend to be a 1GB disk (partition table contains real stuff): */ buf[0] = (disk_size >> 24) & 0xff; buf[1] = (disk_size >> 16) & 0xff; buf[2] = (disk_size >> 8) & 0xff; @@ -323,13 +339,14 @@ simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) buf[5] = 0; buf[6] = 2; buf[7] = 0; + simscsi_fillresult(sc, buf, 8); sc->result = GOOD; break; case MODE_SENSE: case MODE_SENSE_10: /* sd.c uses this to determine whether disk does write-caching. */ - memset(sc->request_buffer, 0, 128); + simscsi_fillresult(sc, (char *)empty_zero_page, sc->request_bufflen); sc->result = GOOD; break; -- cgit v0.10.2 From 40fd3533c93f0062b6d1d8540961ef70fc8ab750 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 13:03:36 -0700 Subject: [SPARC64]: Kill readjust_prom_translations() Testing shows that the prom_unmap() calls do absolutely nothing. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 92d0958..ec47de4 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -619,39 +619,6 @@ static void remap_kernel(void) } } -static void readjust_prom_translations(void) -{ - int nents, i; - - nents = read_obp_translations(); - for (i = 0; i < nents; i++) { - unsigned long vaddr = prom_trans[i].virt; - unsigned long size = prom_trans[i].size; - - if (vaddr < 0xf0000000UL) { - unsigned long avoid_start = (unsigned long) KERNBASE; - unsigned long avoid_end = avoid_start + (4 * 1024 * 1024); - - if (bigkernel) - avoid_end += (4 * 1024 * 1024); - if (vaddr < avoid_start) { - unsigned long top = vaddr + size; - - if (top > avoid_start) - top = avoid_start; - prom_unmap(top - vaddr, vaddr); - } - if ((vaddr + size) > avoid_end) { - unsigned long bottom = vaddr; - - if (bottom < avoid_end) - bottom = avoid_end; - prom_unmap((vaddr + size) - bottom, bottom); - } - } - } -} - static void inherit_prom_mappings(void) { int n; @@ -663,8 +630,6 @@ static void inherit_prom_mappings(void) prom_printf("Remapping the kernel... "); remap_kernel(); - readjust_prom_translations(); - prom_printf("done.\n"); register_prom_callbacks(); -- cgit v0.10.2 From 20bb86852a6b7d9ca8c48ff921ff3904038959cf Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Thu, 22 Sep 2005 18:49:15 +1000 Subject: [IA64] Wire in the MCA/INIT handler stacks Wire the MCA/INIT handler stacks into DTR[2] and track them in IA64_KR(CURRENT_STACK). This gives the MCA/INIT handler stacks the same TLB status as normal kernel stacks. Reload the old CURRENT_STACK data on return from OS to SAL. Signed-off-by: Keith Owens Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 499a065..db32fc1 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -489,24 +489,27 @@ ia64_state_save: ;; st8 [temp1]=r17,16 // pal_min_state st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT + mov r6=IA64_KR(CURRENT_STACK) + ;; + st8 [temp1]=r6,16 // prev_IA64_KR_CURRENT_STACK + st8 [temp2]=r0,16 // prev_task, starts off as NULL mov r6=cr.ifa ;; - st8 [temp1]=r0,16 // prev_task, starts off as NULL - st8 [temp2]=r12,16 // cr.isr + st8 [temp1]=r12,16 // cr.isr + st8 [temp2]=r6,16 // cr.ifa mov r12=cr.itir ;; - st8 [temp1]=r6,16 // cr.ifa - st8 [temp2]=r12,16 // cr.itir + st8 [temp1]=r12,16 // cr.itir + st8 [temp2]=r11,16 // cr.iipa mov r12=cr.iim ;; - st8 [temp1]=r11,16 // cr.iipa - st8 [temp2]=r12,16 // cr.iim - mov r6=cr.iha + st8 [temp1]=r12,16 // cr.iim (p1) mov r12=IA64_MCA_COLD_BOOT (p2) mov r12=IA64_INIT_WARM_BOOT + mov r6=cr.iha ;; - st8 [temp1]=r6,16 // cr.iha - st8 [temp2]=r12 // os_status, default is cold boot + st8 [temp2]=r6,16 // cr.iha + st8 [temp1]=r12 // os_status, default is cold boot mov r6=IA64_MCA_SAME_CONTEXT ;; st8 [temp1]=r6 // context, default is same context @@ -823,9 +826,12 @@ ia64_state_restore: ld8 r12=[temp1],16 // sal_ra ld8 r9=[temp2],16 // sal_gp ;; - ld8 r22=[temp1],24 // pal_min_state, virtual. skip prev_task + ld8 r22=[temp1],16 // pal_min_state, virtual ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT ;; + ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK + ld8 r20=[temp2],16 // prev_task + ;; ld8 temp3=[temp1],16 // cr.isr ld8 temp4=[temp2],16 // cr.ifa ;; @@ -846,6 +852,45 @@ ia64_state_restore: ld8 r8=[temp1] // os_status ld8 r10=[temp2] // context + /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to. To + * avoid any dependencies on the algorithm in ia64_switch_to(), just + * purge any existing CURRENT_STACK mapping and insert the new one. + * + * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains + * prev_IA64_KR_CURRENT, these values may have been changed by the C + * code. Do not use r8, r9, r10, r22, they contain values ready for + * the return to SAL. + */ + + mov r15=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK + ;; + shl r15=r15,IA64_GRANULE_SHIFT + ;; + dep r15=-1,r15,61,3 // virtual granule + mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps + ;; + ptr.d r15,r18 + ;; + srlz.d + + extr.u r19=r21,61,3 // r21 = prev_IA64_KR_CURRENT + shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK + movl r21=PAGE_KERNEL // page properties + ;; + mov IA64_KR(CURRENT_STACK)=r16 + cmp.ne p6,p0=RGN_KERNEL,r19 // new stack is in the kernel region? + or r21=r20,r21 // construct PA | page properties +(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:( + ;; + mov cr.itir=r18 + mov cr.ifa=r21 + mov r20=IA64_TR_CURRENT_STACK + ;; + itr.d dtr[r20]=r21 + ;; + srlz.d +1: + br.sptk b0 //EndStub////////////////////////////////////////////////////////////////////// @@ -982,6 +1027,7 @@ ia64_set_kernel_registers: add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack add r13=temp1, r3 // set current to start of MCA/INIT stack + add r20=temp1, r3 // physical start of MCA/INIT stack ;; ld8 r1=[temp4] // OS GP from SAL OS state ;; @@ -991,7 +1037,35 @@ ia64_set_kernel_registers: ;; mov IA64_KR(CURRENT)=r13 - // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK? + /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid + * any dependencies on the algorithm in ia64_switch_to(), just purge + * any existing CURRENT_STACK mapping and insert the new one. + */ + + mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK + ;; + shl r16=r16,IA64_GRANULE_SHIFT + ;; + dep r16=-1,r16,61,3 // virtual granule + mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps + ;; + ptr.d r16,r18 + ;; + srlz.d + + shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack + movl r21=PAGE_KERNEL // page properties + ;; + mov IA64_KR(CURRENT_STACK)=r16 + or r21=r20,r21 // construct PA | page properties + ;; + mov cr.itir=r18 + mov cr.ifa=r13 + mov r20=IA64_TR_CURRENT_STACK + ;; + itr.d dtr[r20]=r21 + ;; + srlz.d br.sptk b0 diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index 97a28b8..c7d9c9e 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h @@ -80,7 +80,12 @@ struct ia64_sal_os_state { u64 sal_ra; /* Return address in SAL, physical */ u64 sal_gp; /* GP of the SAL - physical */ pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */ + /* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK). + * Note: if the MCA/INIT recovery code wants to resume to a new context + * then it must change these values to reflect the new kernel stack. + */ u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */ + u64 prev_IA64_KR_CURRENT_STACK; struct task_struct *prev_task; /* previous task, NULL if it is not useful */ /* Some interrupt registers are not saved in minstate, pt_regs or * switch_stack. Because MCA/INIT can occur when interrupts are -- cgit v0.10.2 From 4881e2cd25d2d9cf9fca263caff3a0ce732d7d6b Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Tue, 20 Sep 2005 16:34:41 +0900 Subject: [IA64] MCA recovery verify pfn_valid Verify the pfn is valid before calling pfn_to_page(), and cut isolation message if nothing was done. Signed-off-by: Hidetoshi Seto Acked-by: Russ Anderson Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 80f83d6..f081c60 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -56,8 +56,9 @@ static struct page *page_isolate[MAX_PAGE_ISOLATE]; static int num_page_isolate = 0; typedef enum { - ISOLATE_NG = 0, - ISOLATE_OK = 1 + ISOLATE_NG, + ISOLATE_OK, + ISOLATE_NONE } isolate_status_t; /* @@ -74,7 +75,7 @@ static struct { * @paddr: poisoned memory location * * Return value: - * ISOLATE_OK / ISOLATE_NG + * one of isolate_status_t, ISOLATE_OK/NG/NONE. */ static isolate_status_t @@ -85,7 +86,10 @@ mca_page_isolate(unsigned long paddr) /* whether physical address is valid or not */ if (!ia64_phys_addr_valid(paddr)) - return ISOLATE_NG; + return ISOLATE_NONE; + + if (!pfn_valid(paddr)) + return ISOLATE_NONE; /* convert physical address to physical page number */ p = pfn_to_page(paddr>>PAGE_SHIFT); @@ -122,10 +126,15 @@ mca_handler_bh(unsigned long paddr) current->pid, current->comm); spin_lock(&mca_bh_lock); - if (mca_page_isolate(paddr) == ISOLATE_OK) { + switch (mca_page_isolate(paddr)) { + case ISOLATE_OK: printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr); - } else { + break; + case ISOLATE_NG: printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr); + break; + default: + break; } spin_unlock(&mca_bh_lock); -- cgit v0.10.2 From bff06d552240ba7f5b49482a4865871d7bc03dc2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 20:11:33 -0700 Subject: [SPARC64]: Rewrite bootup sequence. Instead of all of this cpu-specific code to remap the kernel to the correct location, use portable firmware calls to do this instead. What we do now is the following in position independant assembler: chosen_node = prom_finddevice("/chosen"); prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu"); vaddr = 4MB_ALIGN(current_text_addr()); prom_translate(vaddr, &paddr_high, &paddr_low, &mode); prom_boot_mapping_mode = mode; prom_boot_mapping_phys_high = paddr_high; prom_boot_mapping_phys_low = paddr_low; prom_map(-1, 8 * 1024 * 1024, KERNBASE, paddr_low); and that replaces the massive amount of by-hand TLB probing and programming we used to do here. The new code should also handle properly the case where the kernel is mapped at the correct address already (think: future kexec support). Consequently, the bulk of remap_kernel() dies as does the entirety of arch/sparc64/prom/map.S We try to share some strings in the PROM library with the ones used at bootup, and while we're here mark input strings to oplib.h routines with "const" when appropriate. There are many more simplifications now possible. For one thing, we can consolidate the two copies we now have of a lot of cpu setup code sitting in head.S and trampoline.S. This is a significant step towards CONFIG_DEBUG_PAGEALLOC support. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index dc3551f..8b83520 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -80,15 +80,165 @@ sparc_ramdisk_image64: .xword 0 .word _end - /* We must be careful, 32-bit OpenBOOT will get confused if it - * tries to save away a register window to a 64-bit kernel - * stack address. Flush all windows, disable interrupts, - * remap if necessary, jump onto kernel trap table, then kernel - * stack, or else we die. + /* PROM cif handler code address is in %o4. */ +sparc64_boot: +1: rd %pc, %g7 + set 1b, %g1 + cmp %g1, %g7 + be,pn %xcc, sparc64_boot_after_remap + mov %o4, %l7 + + /* We need to remap the kernel. Use position independant + * code to remap us to KERNBASE. * - * PROM entry point is on %o4 + * SILO can invoke us with 32-bit address masking enabled, + * so make sure that's clear. */ -sparc64_boot: + rdpr %pstate, %g1 + andn %g1, PSTATE_AM, %g1 + wrpr %g1, 0x0, %pstate + ba,a,pt %xcc, 1f + + .globl prom_finddev_name, prom_chosen_path + .globl prom_getprop_name, prom_mmu_name + .globl prom_callmethod_name, prom_translate_name + .globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache + .globl prom_boot_mapped_pc, prom_boot_mapping_mode + .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low +prom_finddev_name: + .asciz "finddevice" +prom_chosen_path: + .asciz "/chosen" +prom_getprop_name: + .asciz "getprop" +prom_mmu_name: + .asciz "mmu" +prom_callmethod_name: + .asciz "call-method" +prom_translate_name: + .asciz "translate" +prom_map_name: + .asciz "map" +prom_unmap_name: + .asciz "unmap" + .align 4 +prom_mmu_ihandle_cache: + .word 0 +prom_boot_mapped_pc: + .word 0 +prom_boot_mapping_mode: + .word 0 + .align 8 +prom_boot_mapping_phys_high: + .xword 0 +prom_boot_mapping_phys_low: + .xword 0 +1: + rd %pc, %l0 + mov (1b - prom_finddev_name), %l1 + mov (1b - prom_chosen_path), %l2 + mov (1b - prom_boot_mapped_pc), %l3 + sub %l0, %l1, %l1 + sub %l0, %l2, %l2 + sub %l0, %l3, %l3 + stw %l0, [%l3] + sub %sp, (192 + 128), %sp + + /* chosen_node = prom_finddevice("/chosen") */ + stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice" + mov 1, %l3 + stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1 + stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 + stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen" + stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1 + call %l7 + add %sp, (2047 + 128), %o0 ! argument array + + ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node + + mov (1b - prom_getprop_name), %l1 + mov (1b - prom_mmu_name), %l2 + mov (1b - prom_mmu_ihandle_cache), %l5 + sub %l0, %l1, %l1 + sub %l0, %l2, %l2 + sub %l0, %l5, %l5 + + /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */ + stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop" + mov 4, %l3 + stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4 + mov 1, %l3 + stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 + stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node + stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu" + stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache + mov 4, %l3 + stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3) + stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1 + call %l7 + add %sp, (2047 + 128), %o0 ! argument array + + mov (1b - prom_callmethod_name), %l1 + mov (1b - prom_translate_name), %l2 + sub %l0, %l1, %l1 + sub %l0, %l2, %l2 + lduw [%l5], %l5 ! prom_mmu_ihandle_cache + + stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method" + mov 3, %l3 + stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3 + mov 5, %l3 + stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 + stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" + stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache + srlx %l0, 22, %l3 + sllx %l3, 22, %l3 + stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC + stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 + stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 + stx %g0, [%sp + 2047 + 128 + 0x40] ! res3 + stx %g0, [%sp + 2047 + 128 + 0x48] ! res4 + stx %g0, [%sp + 2047 + 128 + 0x50] ! res5 + call %l7 + add %sp, (2047 + 128), %o0 ! argument array + + ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode + mov (1b - prom_boot_mapping_mode), %l4 + sub %l0, %l4, %l4 + stw %l1, [%l4] + mov (1b - prom_boot_mapping_phys_high), %l4 + sub %l0, %l4, %l4 + ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high + stx %l2, [%l4 + 0x0] + ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low + stx %l3, [%l4 + 0x8] + + /* Leave service as-is, "call-method" */ + mov 7, %l3 + stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7 + mov 1, %l3 + stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 7 + mov (1b - prom_map_name), %l3 + sub %l0, %l3, %l3 + stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map" + /* Leave arg2 as-is, prom_mmu_ihandle_cache */ + mov -1, %l3 + stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default) + sethi %hi(8 * 1024 * 1024), %l3 + stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: size (8MB) + sethi %hi(KERNBASE), %l3 + stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE) + stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty + mov (1b - prom_boot_mapping_phys_low), %l3 + sub %l0, %l3, %l3 + ldx [%l3], %l3 + stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr + call %l7 + add %sp, (2047 + 128), %o0 ! argument array + + add %sp, (192 + 128), %sp + +sparc64_boot_after_remap: BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot) BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot) ba,pt %xcc, spitfire_boot @@ -125,185 +275,7 @@ cheetah_generic_boot: stxa %g0, [%g3] ASI_IMMU membar #Sync - wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate - wr %g0, 0, %fprs - - /* Just like for Spitfire, we probe itlb-2 for a mapping which - * matches our current %pc. We take the physical address in - * that mapping and use it to make our own. - */ - - /* %g5 holds the tlb data */ - sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 - sllx %g5, 32, %g5 - or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5 - - /* Put PADDR tlb data mask into %g3. */ - sethi %uhi(_PAGE_PADDR), %g3 - or %g3, %ulo(_PAGE_PADDR), %g3 - sllx %g3, 32, %g3 - sethi %hi(_PAGE_PADDR), %g7 - or %g7, %lo(_PAGE_PADDR), %g7 - or %g3, %g7, %g3 - - set 2 << 16, %l0 /* TLB entry walker. */ - set 0x1fff, %l2 /* Page mask. */ - rd %pc, %l3 - andn %l3, %l2, %g2 /* vaddr comparator */ - -1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - membar #Sync - andn %g1, %l2, %g1 - cmp %g1, %g2 - be,pn %xcc, cheetah_got_tlbentry - nop - and %l0, (127 << 3), %g1 - cmp %g1, (127 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - /* Search the small TLB. OBP never maps us like that but - * newer SILO can. - */ - clr %l0 - -1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - membar #Sync - andn %g1, %l2, %g1 - cmp %g1, %g2 - be,pn %xcc, cheetah_got_tlbentry - nop - cmp %l0, (15 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - /* BUG() if we get here... */ - ta 0x5 - -cheetah_got_tlbentry: - ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0 - ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1 - membar #Sync - and %g1, %g3, %g1 - set 0x5fff, %l0 - andn %g1, %l0, %g1 - or %g5, %g1, %g5 - - /* Clear out any KERNBASE area entries. */ - set 2 << 16, %l0 - sethi %hi(KERNBASE), %g3 - sethi %hi(KERNBASE<<1), %g7 - mov TLB_TAG_ACCESS, %l7 - - /* First, check ITLB */ -1: ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - membar #Sync - andn %g1, %l2, %g1 - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_IMMU - membar #Sync - stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS - membar #Sync - -2: and %l0, (127 << 3), %g1 - cmp %g1, (127 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - /* Next, check DTLB */ - set 2 << 16, %l0 -1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1 - membar #Sync - andn %g1, %l2, %g1 - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_DMMU - membar #Sync - stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS - membar #Sync - -2: and %l0, (511 << 3), %g1 - cmp %g1, (511 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - /* On Cheetah+, have to check second DTLB. */ - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,l0,2f) - ba,pt %xcc, 9f - nop - -2: set 3 << 16, %l0 -1: ldxa [%l0] ASI_DTLB_TAG_READ, %g1 - membar #Sync - andn %g1, %l2, %g1 - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_DMMU - membar #Sync - stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS - membar #Sync - -2: and %l0, (511 << 3), %g1 - cmp %g1, (511 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - -9: - - /* Now lock the TTE we created into ITLB-0 and DTLB-0, - * entry 15 (and maybe 14 too). - */ - sethi %hi(KERNBASE), %g3 - set (0 << 16) | (15 << 3), %g7 - stxa %g3, [%l7] ASI_DMMU - membar #Sync - stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - stxa %g3, [%l7] ASI_IMMU - membar #Sync - stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - flush %g3 - membar #Sync - sethi %hi(_end), %g3 /* Check for bigkernel case */ - or %g3, %lo(_end), %g3 - srl %g3, 23, %g3 /* Check if _end > 8M */ - brz,pt %g3, 1f - sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */ - sethi %hi(0x400000), %g3 - or %g3, %lo(0x400000), %g3 - add %g5, %g3, %g5 /* New tte data */ - andn %g5, (_PAGE_G), %g5 - sethi %hi(KERNBASE+0x400000), %g3 - or %g3, %lo(KERNBASE+0x400000), %g3 - set (0 << 16) | (14 << 3), %g7 - stxa %g3, [%l7] ASI_DMMU - membar #Sync - stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - stxa %g3, [%l7] ASI_IMMU - membar #Sync - stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - flush %g3 - membar #Sync - sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */ - ba,pt %xcc, 1f - nop - -1: set sun4u_init, %g2 - jmpl %g2 + %g0, %g0 - nop + ba,a,pt %xcc, jump_to_sun4u_init spitfire_boot: /* Typically PROM has already enabled both MMU's and both on-chip @@ -313,6 +285,7 @@ spitfire_boot: stxa %g1, [%g0] ASI_LSU_CONTROL membar #Sync +jump_to_sun4u_init: /* * Make sure we are in privileged mode, have address masking, * using the ordinary globals and have enabled floating @@ -324,151 +297,6 @@ spitfire_boot: wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate wr %g0, 0, %fprs -spitfire_create_mappings: - /* %g5 holds the tlb data */ - sethi %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5 - sllx %g5, 32, %g5 - or %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5 - - /* Base of physical memory cannot reliably be assumed to be - * at 0x0! Figure out where it happens to be. -DaveM - */ - - /* Put PADDR tlb data mask into %g3. */ - sethi %uhi(_PAGE_PADDR_SF), %g3 - or %g3, %ulo(_PAGE_PADDR_SF), %g3 - sllx %g3, 32, %g3 - sethi %hi(_PAGE_PADDR_SF), %g7 - or %g7, %lo(_PAGE_PADDR_SF), %g7 - or %g3, %g7, %g3 - - /* Walk through entire ITLB, looking for entry which maps - * our %pc currently, stick PADDR from there into %g5 tlb data. - */ - clr %l0 /* TLB entry walker. */ - set 0x1fff, %l2 /* Page mask. */ - rd %pc, %l3 - andn %l3, %l2, %g2 /* vaddr comparator */ -1: - /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */ - ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 /* Get vaddr */ - cmp %g1, %g2 - be,a,pn %xcc, spitfire_got_tlbentry - ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1 - cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - /* BUG() if we get here... */ - ta 0x5 - -spitfire_got_tlbentry: - /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */ - nop - nop - nop - and %g1, %g3, %g1 /* Mask to just get paddr bits. */ - set 0x5fff, %l3 /* Mask offset to get phys base. */ - andn %g1, %l3, %g1 - - /* NOTE: We hold on to %g1 paddr base as we need it below to lock - * NOTE: the PROM cif code into the TLB. - */ - - or %g5, %g1, %g5 /* Or it into TAG being built. */ - - clr %l0 /* TLB entry walker. */ - sethi %hi(KERNBASE), %g3 /* 4M lower limit */ - sethi %hi(KERNBASE<<1), %g7 /* 8M upper limit */ - mov TLB_TAG_ACCESS, %l7 -1: - /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */ - ldxa [%l0] ASI_ITLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 /* Get vaddr */ - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_IMMU - stxa %g0, [%l0] ASI_ITLB_DATA_ACCESS - membar #Sync -2: - cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - nop; nop; nop - - clr %l0 /* TLB entry walker. */ -1: - /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */ - ldxa [%l0] ASI_DTLB_TAG_READ, %g1 - nop - nop - nop - andn %g1, %l2, %g1 /* Get vaddr */ - cmp %g1, %g3 - blu,pn %xcc, 2f - cmp %g1, %g7 - bgeu,pn %xcc, 2f - nop - stxa %g0, [%l7] ASI_DMMU - stxa %g0, [%l0] ASI_DTLB_DATA_ACCESS - membar #Sync -2: - cmp %l0, (63 << 3) - blu,pt %xcc, 1b - add %l0, (1 << 3), %l0 - - nop; nop; nop - - - /* PROM never puts any TLB entries into the MMU with the lock bit - * set. So we gladly use tlb entry 63 for KERNBASE. And maybe 62 too. - */ - - sethi %hi(KERNBASE), %g3 - mov (63 << 3), %g7 - stxa %g3, [%l7] ASI_DMMU /* KERNBASE into TLB TAG */ - stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA */ - membar #Sync - stxa %g3, [%l7] ASI_IMMU /* KERNBASE into TLB TAG */ - stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA */ - membar #Sync - flush %g3 - membar #Sync - sethi %hi(_end), %g3 /* Check for bigkernel case */ - or %g3, %lo(_end), %g3 - srl %g3, 23, %g3 /* Check if _end > 8M */ - brz,pt %g3, 2f - sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */ - sethi %hi(0x400000), %g3 - or %g3, %lo(0x400000), %g3 - add %g5, %g3, %g5 /* New tte data */ - andn %g5, (_PAGE_G), %g5 - sethi %hi(KERNBASE+0x400000), %g3 - or %g3, %lo(KERNBASE+0x400000), %g3 - mov (62 << 3), %g7 - stxa %g3, [%l7] ASI_DMMU - stxa %g5, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - stxa %g3, [%l7] ASI_IMMU - stxa %g5, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - flush %g3 - membar #Sync - sethi %hi(KERNBASE), %g3 /* Restore for fixup code below */ -2: ba,pt %xcc, 1f - nop -1: set sun4u_init, %g2 jmpl %g2 + %g0, %g0 nop @@ -483,38 +311,12 @@ sun4u_init: stxa %g0, [%g7] ASI_DMMU membar #Sync - /* We are now safely (we hope) in Nucleus context (0), rewrite - * the KERNBASE TTE's so they no longer have the global bit set. - * Don't forget to setup TAG_ACCESS first 8-) - */ - mov TLB_TAG_ACCESS, %g2 - stxa %g3, [%g2] ASI_IMMU - stxa %g3, [%g2] ASI_DMMU - membar #Sync - BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup) ba,pt %xcc, spitfire_tlb_fixup nop cheetah_tlb_fixup: - set (0 << 16) | (15 << 3), %g7 - ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g0 - ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - - ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g0 - ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - - /* Kill instruction prefetch queues. */ - flush %g3 - membar #Sync - mov 2, %g2 /* Set TLB type to cheetah+. */ BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) @@ -551,21 +353,6 @@ cheetah_tlb_fixup: nop spitfire_tlb_fixup: - mov (63 << 3), %g7 - ldxa [%g7] ASI_ITLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_ITLB_DATA_ACCESS - membar #Sync - - ldxa [%g7] ASI_DTLB_DATA_ACCESS, %g1 - andn %g1, (_PAGE_G), %g1 - stxa %g1, [%g7] ASI_DTLB_DATA_ACCESS - membar #Sync - - /* Kill instruction prefetch queues. */ - flush %g3 - membar #Sync - /* Set TLB type to spitfire. */ mov 0, %g2 sethi %hi(tlb_type), %g1 @@ -578,24 +365,6 @@ tlb_fixup_done: mov %sp, %l6 mov %o4, %l7 -#if 0 /* We don't do it like this anymore, but for historical hack value - * I leave this snippet here to show how crazy we can be sometimes. 8-) - */ - - /* Setup "Linux Current Register", thanks Sun 8-) */ - wr %g0, 0x1, %pcr - - /* Blackbird errata workaround. See commentary in - * smp.c:smp_percpu_timer_interrupt() for more - * information. - */ - ba,pt %xcc, 99f - nop - .align 64 -99: wr %g6, %g0, %pic - rd %pic, %g0 -#endif - wr %g0, ASI_P, %asi mov 1, %g1 sllx %g1, THREAD_SHIFT, %g1 diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index ddbed33..0296cb0 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -536,20 +536,7 @@ void __init setup_arch(char **cmdline_p) } pfn_base = phys_base >> PAGE_SHIFT; - switch (tlb_type) { - default: - case spitfire: - kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent()); - kern_base &= _PAGE_PADDR_SF; - break; - - case cheetah: - case cheetah_plus: - kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent()); - kern_base &= _PAGE_PADDR; - break; - }; - + kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; if (!root_flags) diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 3a145fc..89f2fcf 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -119,8 +119,8 @@ startup_continue: sethi %hi(itlb_load), %g2 or %g2, %lo(itlb_load), %g2 stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + sethi %hi(prom_mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] sethi %hi(KERNBASE), %g2 stx %g2, [%sp + 2047 + 128 + 0x28] @@ -156,8 +156,8 @@ startup_continue: sethi %hi(itlb_load), %g2 or %g2, %lo(itlb_load), %g2 stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + sethi %hi(prom_mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] sethi %hi(KERNBASE + 0x400000), %g2 stx %g2, [%sp + 2047 + 128 + 0x28] @@ -190,8 +190,8 @@ do_dtlb: sethi %hi(dtlb_load), %g2 or %g2, %lo(dtlb_load), %g2 stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + sethi %hi(prom_mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] sethi %hi(KERNBASE), %g2 stx %g2, [%sp + 2047 + 128 + 0x28] @@ -228,8 +228,8 @@ do_dtlb: sethi %hi(dtlb_load), %g2 or %g2, %lo(dtlb_load), %g2 stx %g2, [%sp + 2047 + 128 + 0x18] - sethi %hi(mmu_ihandle_cache), %g2 - lduw [%g2 + %lo(mmu_ihandle_cache)], %g2 + sethi %hi(prom_mmu_ihandle_cache), %g2 + lduw [%g2 + %lo(prom_mmu_ihandle_cache)], %g2 stx %g2, [%sp + 2047 + 128 + 0x20] sethi %hi(KERNBASE + 0x400000), %g2 stx %g2, [%sp + 2047 + 128 + 0x28] diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index ec47de4..e0b9eeb 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -505,108 +505,20 @@ static int read_obp_translations(void) return n; } -static inline void early_spitfire_errata32(void) -{ - /* Spitfire Errata #32 workaround */ - /* NOTE: Using plain zero for the context value is - * correct here, we are not using the Linux trap - * tables yet so we should not use the special - * UltraSPARC-III+ page size encodings yet. - */ - __asm__ __volatile__("stxa %0, [%1] %2\n\t" - "flush %%g6" - : /* No outputs */ - : "r" (0), "r" (PRIMARY_CONTEXT), - "i" (ASI_DMMU)); -} - -static void lock_remap_func_page(unsigned long phys_page) -{ - unsigned long tte_data = (phys_page | pgprot_val(PAGE_KERNEL)); - - if (tlb_type == spitfire) { - /* Lock this into i/d tlb entry 59 */ - __asm__ __volatile__( - "stxa %%g0, [%2] %3\n\t" - "stxa %0, [%1] %4\n\t" - "membar #Sync\n\t" - "flush %%g6\n\t" - "stxa %%g0, [%2] %5\n\t" - "stxa %0, [%1] %6\n\t" - "membar #Sync\n\t" - "flush %%g6" - : /* no outputs */ - : "r" (tte_data), "r" (59 << 3), "r" (TLB_TAG_ACCESS), - "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), - "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS) - : "memory"); - } else { - /* Lock this into i/d tlb-0 entry 11 */ - __asm__ __volatile__( - "stxa %%g0, [%2] %3\n\t" - "stxa %0, [%1] %4\n\t" - "membar #Sync\n\t" - "flush %%g6\n\t" - "stxa %%g0, [%2] %5\n\t" - "stxa %0, [%1] %6\n\t" - "membar #Sync\n\t" - "flush %%g6" - : /* no outputs */ - : "r" (tte_data), "r" ((0 << 16) | (11 << 3)), - "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU), - "i" (ASI_DTLB_DATA_ACCESS), "i" (ASI_IMMU), - "i" (ASI_ITLB_DATA_ACCESS) - : "memory"); - } -} - static void remap_kernel(void) { unsigned long phys_page, tte_vaddr, tte_data; - void (*remap_func)(unsigned long, unsigned long, int); int tlb_ent = sparc64_highest_locked_tlbent(); - early_spitfire_errata32(); - - if (tlb_type == spitfire) - phys_page = spitfire_get_dtlb_data(tlb_ent); - else - phys_page = cheetah_get_ldtlb_data(tlb_ent); - - phys_page &= _PAGE_PADDR; - phys_page += ((unsigned long)&prom_boot_page - - (unsigned long)KERNBASE); - - lock_remap_func_page(phys_page); - tte_vaddr = (unsigned long) KERNBASE; - - early_spitfire_errata32(); - - if (tlb_type == spitfire) - tte_data = spitfire_get_dtlb_data(tlb_ent); - else - tte_data = cheetah_get_ldtlb_data(tlb_ent); + phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL; + tte_data = (phys_page | (_PAGE_VALID | _PAGE_SZ4MB | + _PAGE_CP | _PAGE_CV | _PAGE_P | + _PAGE_L | _PAGE_W)); kern_locked_tte_data = tte_data; - remap_func = (void *) ((unsigned long) &prom_remap - - (unsigned long) &prom_boot_page); - - early_spitfire_errata32(); - - phys_page = tte_data & _PAGE_PADDR; - remap_func(phys_page, KERNBASE, prom_get_mmu_ihandle()); - if (bigkernel) - remap_func(phys_page + 0x400000, - KERNBASE + 0x400000, - prom_get_mmu_ihandle()); - - /* Flush out that temporary mapping. */ - spitfire_flush_dtlb_nucleus_page(0x0); - spitfire_flush_itlb_nucleus_page(0x0); - - /* Now lock us back into the TLBs via OBP. */ + /* Now lock us into the TLBs via OBP. */ prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); prom_itlb_load(tlb_ent, tte_data, tte_vaddr); if (bigkernel) { diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile index 8f2420d..c7898a5 100644 --- a/arch/sparc64/prom/Makefile +++ b/arch/sparc64/prom/Makefile @@ -7,4 +7,4 @@ EXTRA_AFLAGS := -ansi EXTRA_CFLAGS := -Werror lib-y := bootstr.o devops.o init.o memory.o misc.o \ - tree.o console.o printf.o p1275.o map.o cif.o + tree.o console.o printf.o p1275.o cif.o diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c index 028a53f..eae5db8 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc64/prom/console.c @@ -67,7 +67,7 @@ prom_putchar(char c) } void -prom_puts(char *s, int len) +prom_puts(const char *s, int len) { p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)| P1275_INOUT(3,1), diff --git a/arch/sparc64/prom/devops.c b/arch/sparc64/prom/devops.c index 2c99b21..4641839 100644 --- a/arch/sparc64/prom/devops.c +++ b/arch/sparc64/prom/devops.c @@ -16,7 +16,7 @@ * Returns 0 on failure. */ int -prom_devopen(char *dstr) +prom_devopen(const char *dstr) { return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)| P1275_INOUT(1,1), diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c index 817faae..8b4b622 100644 --- a/arch/sparc64/prom/init.c +++ b/arch/sparc64/prom/init.c @@ -46,7 +46,7 @@ void __init prom_init(void *cif_handler, void *cif_stack) if((prom_root_node == 0) || (prom_root_node == -1)) prom_halt(); - prom_chosen_node = prom_finddevice("/chosen"); + prom_chosen_node = prom_finddevice(prom_chosen_path); if (!prom_chosen_node || prom_chosen_node == -1) prom_halt(); diff --git a/arch/sparc64/prom/map.S b/arch/sparc64/prom/map.S deleted file mode 100644 index 21b3f9c..0000000 --- a/arch/sparc64/prom/map.S +++ /dev/null @@ -1,72 +0,0 @@ -/* $Id: map.S,v 1.2 1999/11/19 05:53:02 davem Exp $ - * map.S: Tricky coding required to fixup the kernel OBP maps - * properly. - * - * Copyright (C) 1999 David S. Miller (davem@redhat.com) - */ - - .text - .align 8192 - .globl prom_boot_page -prom_boot_page: -call_method: - .asciz "call-method" - .align 8 -map: - .asciz "map" - .align 8 - - /* When we are invoked, our caller has remapped us to - * page zero, therefore we must use PC relative addressing - * for everything after we begin performing the unmap/map - * calls. - */ - .globl prom_remap -prom_remap: /* %o0 = physpage, %o1 = virtpage, %o2 = mmu_ihandle */ - rd %pc, %g1 - srl %o2, 0, %o2 ! kill sign extension - sethi %hi(p1275buf), %g2 - or %g2, %lo(p1275buf), %g2 - ldx [%g2 + 0x10], %g3 ! prom_cif_stack - save %g3, -(192 + 128), %sp - ldx [%g2 + 0x08], %l0 ! prom_cif_handler - mov %g6, %i3 - mov %g4, %i4 - mov %g5, %i5 - flushw - - sethi %hi(prom_remap - call_method), %g7 - or %g7, %lo(prom_remap - call_method), %g7 - sub %g1, %g7, %l2 ! call-method string - sethi %hi(prom_remap - map), %g7 - or %g7, %lo(prom_remap - map), %g7 - sub %g1, %g7, %l4 ! map string - - /* OK, map the 4MB region we really live at. */ - stx %l2, [%sp + 2047 + 128 + 0x00] ! call-method - mov 7, %l5 - stx %l5, [%sp + 2047 + 128 + 0x08] ! num_args - mov 1, %l5 - stx %l5, [%sp + 2047 + 128 + 0x10] ! num_rets - stx %l4, [%sp + 2047 + 128 + 0x18] ! map - stx %i2, [%sp + 2047 + 128 + 0x20] ! mmu_ihandle - mov -1, %l5 - stx %l5, [%sp + 2047 + 128 + 0x28] ! mode == default - sethi %hi(4 * 1024 * 1024), %l5 - stx %l5, [%sp + 2047 + 128 + 0x30] ! size - stx %i1, [%sp + 2047 + 128 + 0x38] ! vaddr - stx %g0, [%sp + 2047 + 128 + 0x40] ! filler - stx %i0, [%sp + 2047 + 128 + 0x48] ! paddr - call %l0 - add %sp, (2047 + 128), %o0 ! argument array - - /* Restore hard-coded globals. */ - mov %i3, %g6 - mov %i4, %g4 - mov %i5, %g5 - - /* Wheee.... we are done. */ - ret - restore - - .align 8192 diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index 19c44e9..9b895fa 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c @@ -17,14 +17,14 @@ #include /* Reset and reboot the machine with the command 'bcommand'. */ -void prom_reboot(char *bcommand) +void prom_reboot(const char *bcommand) { p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_INOUT(1, 0), bcommand); } /* Forth evaluate the expression contained in 'fstring'. */ -void prom_feval(char *fstring) +void prom_feval(const char *fstring) { if (!fstring || fstring[0] == 0) return; @@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba) p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba); } -int mmu_ihandle_cache = 0; - int prom_get_mmu_ihandle(void) { int node, ret; - if (mmu_ihandle_cache != 0) - return mmu_ihandle_cache; + if (prom_mmu_ihandle_cache != 0) + return prom_mmu_ihandle_cache; - node = prom_finddevice("/chosen"); - ret = prom_getint(node, "mmu"); + node = prom_finddevice(prom_chosen_path); + ret = prom_getint(node, prom_mmu_name); if (ret == -1 || ret == 0) - mmu_ihandle_cache = -1; + prom_mmu_ihandle_cache = -1; else - mmu_ihandle_cache = ret; + prom_mmu_ihandle_cache = ret; return ret; } @@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index, unsigned long tte_data, unsigned long vaddr) { - return p1275_cmd("call-method", + return p1275_cmd(prom_callmethod_name, (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) | @@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index, unsigned long tte_data, unsigned long vaddr) { - return p1275_cmd("call-method", + return p1275_cmd(prom_callmethod_name, (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) | @@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index, int prom_map(int mode, unsigned long size, unsigned long vaddr, unsigned long paddr) { - int ret = p1275_cmd("call-method", + int ret = p1275_cmd(prom_callmethod_name, (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(3, P1275_ARG_IN_64B) | P1275_ARG(4, P1275_ARG_IN_64B) | P1275_ARG(6, P1275_ARG_IN_64B) | P1275_INOUT(7, 1)), - "map", + prom_map_name, prom_get_mmu_ihandle(), mode, size, @@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size, void prom_unmap(unsigned long size, unsigned long vaddr) { - p1275_cmd("call-method", + p1275_cmd(prom_callmethod_name, (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(2, P1275_ARG_IN_64B) | P1275_ARG(3, P1275_ARG_IN_64B) | P1275_INOUT(4, 0)), - "unmap", + prom_unmap_name, prom_get_mmu_ihandle(), size, vaddr); @@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr) /* Set aside physical memory which is not touched or modified * across soft resets. */ -unsigned long prom_retain(char *name, +unsigned long prom_retain(const char *name, unsigned long pa_low, unsigned long pa_high, long size, long align) { @@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) { - return p1275_cmd("call-method", + return p1275_cmd(prom_callmethod_name, (P1275_ARG(0, P1275_ARG_IN_STRING) | P1275_ARG(3, P1275_ARG_OUT_BUF) | P1275_ARG(6, P1275_ARG_IN_64B) | diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c index 59fe38b..a5a7c571 100644 --- a/arch/sparc64/prom/p1275.c +++ b/arch/sparc64/prom/p1275.c @@ -46,7 +46,7 @@ static inline unsigned long spitfire_get_primary_context(void) */ DEFINE_SPINLOCK(prom_entry_lock); -long p1275_cmd (char *service, long fmt, ...) +long p1275_cmd(const char *service, long fmt, ...) { char *p, *q; unsigned long flags; diff --git a/arch/sparc64/prom/printf.c b/arch/sparc64/prom/printf.c index a6df82c..660943e 100644 --- a/arch/sparc64/prom/printf.c +++ b/arch/sparc64/prom/printf.c @@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n) } void -prom_printf(char *fmt, ...) +prom_printf(const char *fmt, ...) { va_list args; int i; diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c index ccf7325..b1ff9e8 100644 --- a/arch/sparc64/prom/tree.c +++ b/arch/sparc64/prom/tree.c @@ -69,7 +69,7 @@ prom_getsibling(int node) * Return -1 on error. */ __inline__ int -prom_getproplen(int node, char *prop) +prom_getproplen(int node, const char *prop) { if((!node) || (!prop)) return -1; return p1275_cmd ("getproplen", @@ -83,20 +83,20 @@ prom_getproplen(int node, char *prop) * was successful the length will be returned, else -1 is returned. */ __inline__ int -prom_getproperty(int node, char *prop, char *buffer, int bufsize) +prom_getproperty(int node, const char *prop, char *buffer, int bufsize) { int plen; plen = prom_getproplen(node, prop); - if((plen > bufsize) || (plen == 0) || (plen == -1)) + if ((plen > bufsize) || (plen == 0) || (plen == -1)) { return -1; - else { + } else { /* Ok, things seem all right. */ - return p1275_cmd ("getprop", - P1275_ARG(1,P1275_ARG_IN_STRING)| - P1275_ARG(2,P1275_ARG_OUT_BUF)| - P1275_INOUT(4, 1), - node, prop, buffer, P1275_SIZE(plen)); + return p1275_cmd(prom_getprop_name, + P1275_ARG(1,P1275_ARG_IN_STRING)| + P1275_ARG(2,P1275_ARG_OUT_BUF)| + P1275_INOUT(4, 1), + node, prop, buffer, P1275_SIZE(plen)); } } @@ -104,7 +104,7 @@ prom_getproperty(int node, char *prop, char *buffer, int bufsize) * on failure. */ __inline__ int -prom_getint(int node, char *prop) +prom_getint(int node, const char *prop) { int intprop; @@ -119,7 +119,7 @@ prom_getint(int node, char *prop) */ int -prom_getintdefault(int node, char *property, int deflt) +prom_getintdefault(int node, const char *property, int deflt) { int retval; @@ -131,7 +131,7 @@ prom_getintdefault(int node, char *property, int deflt) /* Acquire a boolean property, 1=TRUE 0=FALSE. */ int -prom_getbool(int node, char *prop) +prom_getbool(int node, const char *prop) { int retval; @@ -145,7 +145,7 @@ prom_getbool(int node, char *prop) * buffer. */ void -prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) +prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) { int len; @@ -160,7 +160,7 @@ prom_getstring(int node, char *prop, char *user_buf, int ubuf_size) * YES = 1 NO = 0 */ int -prom_nodematch(int node, char *name) +prom_nodematch(int node, const char *name) { char namebuf[128]; prom_getproperty(node, "name", namebuf, sizeof(namebuf)); @@ -172,7 +172,7 @@ prom_nodematch(int node, char *name) * 'nodename'. Return node if successful, zero if not. */ int -prom_searchsiblings(int node_start, char *nodename) +prom_searchsiblings(int node_start, const char *nodename) { int thisnode, error; @@ -294,7 +294,7 @@ prom_firstprop(int node, char *buffer) * property types for this node. */ __inline__ char * -prom_nextprop(int node, char *oprop, char *buffer) +prom_nextprop(int node, const char *oprop, char *buffer) { char buf[32]; @@ -314,15 +314,17 @@ prom_nextprop(int node, char *oprop, char *buffer) } int -prom_finddevice(char *name) +prom_finddevice(const char *name) { - if(!name) return 0; - return p1275_cmd ("finddevice", P1275_ARG(0,P1275_ARG_IN_STRING)| - P1275_INOUT(1, 1), - name); + if (!name) + return 0; + return p1275_cmd(prom_finddev_name, + P1275_ARG(0,P1275_ARG_IN_STRING)| + P1275_INOUT(1, 1), + name); } -int prom_node_has_property(int node, char *prop) +int prom_node_has_property(int node, const char *prop) { char buf [32]; @@ -339,7 +341,7 @@ int prom_node_has_property(int node, char *prop) * of 'size' bytes. Return the number of bytes the prom accepted. */ int -prom_setprop(int node, char *pname, char *value, int size) +prom_setprop(int node, const char *pname, char *value, int size) { if(size == 0) return 0; if((pname == 0) || (value == 0)) return 0; @@ -364,7 +366,7 @@ prom_inst2pkg(int inst) * FIXME: Should work for v0 as well */ int -prom_pathtoinode(char *path) +prom_pathtoinode(const char *path) { int node, inst; diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h index a432d9e..c628189 100644 --- a/include/asm-sparc64/oplib.h +++ b/include/asm-sparc64/oplib.h @@ -38,6 +38,20 @@ extern int prom_stdin, prom_stdout; */ extern int prom_chosen_node; +/* Helper values and strings in arch/sparc64/kernel/head.S */ +extern const char prom_finddev_name[]; +extern const char prom_chosen_path[]; +extern const char prom_getprop_name[]; +extern const char prom_mmu_name[]; +extern const char prom_callmethod_name[]; +extern const char prom_translate_name[]; +extern const char prom_map_name[]; +extern const char prom_unmap_name[]; +extern int prom_mmu_ihandle_cache; +extern unsigned int prom_boot_mapped_pc; +extern unsigned int prom_boot_mapping_mode; +extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low; + struct linux_mlist_p1275 { struct linux_mlist_p1275 *theres_more; unsigned long start_adr; @@ -68,7 +82,7 @@ extern char *prom_getbootargs(void); * of the string is different on V0 vs. V2->higher proms. The caller must * know what he/she is doing! Returns the device descriptor, an int. */ -extern int prom_devopen(char *device_string); +extern int prom_devopen(const char *device_string); /* Close a previously opened device described by the passed integer * descriptor. @@ -98,10 +112,10 @@ extern struct linux_mem_p1275 *prom_meminfo(void); /* Miscellaneous routines, don't really fit in any category per se. */ /* Reboot the machine with the command line passed. */ -extern void prom_reboot(char *boot_command); +extern void prom_reboot(const char *boot_command); /* Evaluate the forth string passed. */ -extern void prom_feval(char *forth_string); +extern void prom_feval(const char *forth_string); /* Enter the prom, with possibility of continuation with the 'go' * command in newer proms. @@ -154,7 +168,7 @@ extern char prom_getchar(void); extern void prom_putchar(char character); /* Prom's internal routines, don't use in kernel/boot code. */ -extern void prom_printf(char *fmt, ...); +extern void prom_printf(const char *fmt, ...); extern void prom_write(const char *buf, unsigned int len); /* Query for input device type */ @@ -215,7 +229,7 @@ extern int prom_getunumber(int syndrome_code, char *buf, int buflen); /* Retain physical memory to the caller across soft resets. */ -extern unsigned long prom_retain(char *name, +extern unsigned long prom_retain(const char *name, unsigned long pa_low, unsigned long pa_high, long size, long align); @@ -269,28 +283,28 @@ extern int prom_getsibling(int node); /* Get the length, at the passed node, of the given property type. * Returns -1 on error (ie. no such property at this node). */ -extern int prom_getproplen(int thisnode, char *property); +extern int prom_getproplen(int thisnode, const char *property); /* Fetch the requested property using the given buffer. Returns * the number of bytes the prom put into your buffer or -1 on error. */ -extern int prom_getproperty(int thisnode, char *property, +extern int prom_getproperty(int thisnode, const char *property, char *prop_buffer, int propbuf_size); /* Acquire an integer property. */ -extern int prom_getint(int node, char *property); +extern int prom_getint(int node, const char *property); /* Acquire an integer property, with a default value. */ -extern int prom_getintdefault(int node, char *property, int defval); +extern int prom_getintdefault(int node, const char *property, int defval); /* Acquire a boolean property, 0=FALSE 1=TRUE. */ -extern int prom_getbool(int node, char *prop); +extern int prom_getbool(int node, const char *prop); /* Acquire a string property, null string on error. */ -extern void prom_getstring(int node, char *prop, char *buf, int bufsize); +extern void prom_getstring(int node, const char *prop, char *buf, int bufsize); /* Does the passed node have the given "name"? YES=1 NO=0 */ -extern int prom_nodematch(int thisnode, char *name); +extern int prom_nodematch(int thisnode, const char *name); /* Puts in buffer a prom name in the form name@x,y or name (x for which_io * and y for first regs phys address @@ -300,7 +314,7 @@ extern int prom_getname(int node, char *buf, int buflen); /* Search all siblings starting at the passed node for "name" matching * the given string. Returns the node on success, zero on failure. */ -extern int prom_searchsiblings(int node_start, char *name); +extern int prom_searchsiblings(int node_start, const char *name); /* Return the first property type, as a string, for the given node. * Returns a null string on error. Buffer should be at least 32B long. @@ -310,21 +324,21 @@ extern char *prom_firstprop(int node, char *buffer); /* Returns the next property after the passed property for the given * node. Returns null string on failure. Buffer should be at least 32B long. */ -extern char *prom_nextprop(int node, char *prev_property, char *buffer); +extern char *prom_nextprop(int node, const char *prev_property, char *buffer); /* Returns 1 if the specified node has given property. */ -extern int prom_node_has_property(int node, char *property); +extern int prom_node_has_property(int node, const char *property); /* Returns phandle of the path specified */ -extern int prom_finddevice(char *name); +extern int prom_finddevice(const char *name); /* Set the indicated property at the given node with the passed value. * Returns the number of bytes of your value that the prom took. */ -extern int prom_setprop(int node, char *prop_name, char *prop_value, +extern int prom_setprop(int node, const char *prop_name, char *prop_value, int value_size); -extern int prom_pathtoinode(char *path); +extern int prom_pathtoinode(const char *path); extern int prom_inst2pkg(int); /* CPU probing helpers. */ @@ -334,7 +348,7 @@ int cpu_find_by_mid(int mid, int *prom_node); /* Client interface level routines. */ extern void prom_set_trap_table(unsigned long tba); -extern long p1275_cmd (char *, long, ...); +extern long p1275_cmd(const char *, long, ...); #if 0 -- cgit v0.10.2 From a8201c61065f3b5a4fe2fde1db1c817e288916be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 22 Sep 2005 20:31:29 -0700 Subject: [SPARC64]: Fix comment typo in head.S Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 8b83520..56af714 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -217,7 +217,7 @@ prom_boot_mapping_phys_low: mov 7, %l3 stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7 mov 1, %l3 - stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 7 + stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1 mov (1b - prom_map_name), %l3 sub %l0, %l3, %l3 stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map" -- cgit v0.10.2 From 0678e5feaab8b359b18858e8532bb6017edb112b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 22 Sep 2005 21:43:44 -0700 Subject: [PATCH] proc_task_root_link c99 fix fs/proc/base.c: In function `proc_task_root_link': fs/proc/base.c:364: warning: ISO C90 forbids mixed declarations and code Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index fb34f88..3b33f94 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -343,7 +343,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf /* Same as proc_root_link, but this addionally tries to get fs from other * threads in the group */ -static int proc_task_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +static int proc_task_root_link(struct inode *inode, struct dentry **dentry, + struct vfsmount **mnt) { struct fs_struct *fs; int result = -ENOENT; @@ -357,9 +358,10 @@ static int proc_task_root_link(struct inode *inode, struct dentry **dentry, stru } else { /* Try to get fs from other threads */ task_unlock(leader); - struct task_struct *task = leader; read_lock(&tasklist_lock); - if (pid_alive(task)) { + if (pid_alive(leader)) { + struct task_struct *task = leader; + while ((task = next_thread(task)) != leader) { task_lock(task); fs = task->fs; -- cgit v0.10.2 From e4c94330e3395ae87451bded2840a25d04f27902 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 22 Sep 2005 21:43:45 -0700 Subject: [PATCH] reboot: comment and factor the main reboot functions In the lead up to 2.6.13 I fixed a large number of reboot problems by making the calling conventions consistent. Despite checking and double checking my work it appears I missed an obvious one. This first patch simply refactors the reboot routines so all of the preparation for various kinds of reboots are in their own functions. Making it very hard to get the various kinds of reboot out of sync. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 3b3266f..7ab2cdb 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -59,6 +59,10 @@ extern void machine_crash_shutdown(struct pt_regs *); * Architecture independent implemenations of sys_reboot commands. */ +extern void kernel_restart_prepare(char *cmd); +extern void kernel_halt_prepare(void); +extern void kernel_power_off_prepare(void); + extern void kernel_restart(char *cmd); extern void kernel_halt(void); extern void kernel_power_off(void); diff --git a/kernel/sys.c b/kernel/sys.c index f723522..2fa1ed1 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -361,17 +361,35 @@ out_unlock: return retval; } +/** + * emergency_restart - reboot the system + * + * Without shutting down any hardware or taking any locks + * reboot the system. This is called when we know we are in + * trouble so this is our best effort to reboot. This is + * safe to call in interrupt context. + */ void emergency_restart(void) { machine_emergency_restart(); } EXPORT_SYMBOL_GPL(emergency_restart); -void kernel_restart(char *cmd) +/** + * kernel_restart - reboot the system + * + * Shutdown everything and perform a clean reboot. + * This is not safe to call in interrupt context. + */ +void kernel_restart_prepare(char *cmd) { notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; device_shutdown(); +} +void kernel_restart(char *cmd) +{ + kernel_restart_prepare(cmd); if (!cmd) { printk(KERN_EMERG "Restarting system.\n"); } else { @@ -382,6 +400,12 @@ void kernel_restart(char *cmd) } EXPORT_SYMBOL_GPL(kernel_restart); +/** + * kernel_kexec - reboot the system + * + * Move into place and start executing a preloaded standalone + * executable. If nothing was preloaded return an error. + */ void kernel_kexec(void) { #ifdef CONFIG_KEXEC @@ -390,9 +414,7 @@ void kernel_kexec(void) if (!image) { return; } - notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL); - system_state = SYSTEM_RESTART; - device_shutdown(); + kernel_restart_prepare(NULL); printk(KERN_EMERG "Starting new kernel\n"); machine_shutdown(); machine_kexec(image); @@ -400,21 +422,39 @@ void kernel_kexec(void) } EXPORT_SYMBOL_GPL(kernel_kexec); -void kernel_halt(void) +/** + * kernel_halt - halt the system + * + * Shutdown everything and perform a clean system halt. + */ +void kernel_halt_prepare(void) { notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); system_state = SYSTEM_HALT; device_shutdown(); +} +void kernel_halt(void) +{ + kernel_halt_prepare(); printk(KERN_EMERG "System halted.\n"); machine_halt(); } EXPORT_SYMBOL_GPL(kernel_halt); -void kernel_power_off(void) +/** + * kernel_power_off - power_off the system + * + * Shutdown everything and perform a clean system power_off. + */ +void kernel_power_off_prepare(void) { notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); system_state = SYSTEM_POWER_OFF; device_shutdown(); +} +void kernel_power_off(void) +{ + kernel_power_off_prepare(); printk(KERN_EMERG "Power down.\n"); machine_power_off(); } -- cgit v0.10.2 From 88d10bbaaec38856f913313b6c0858d9e9b7a066 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 22 Sep 2005 21:43:46 -0700 Subject: [PATCH] suspend: cleanup calling of power off methods. In the lead up to 2.6.13 I fixed a large number of reboot problems by making the calling conventions consistent. Despite checking and double checking my work it appears I missed an obvious one. The S4 suspend code for PM_DISK_PLATFORM was also calling device_shutdown without setting system_state, and was not calling the appropriate reboot_notifier. This patch fixes the bug by replacing the call of device_suspend with kernel_poweroff_prepare. Various forms of this failure have been fixed and tracked for a while. Thanks for tracking this down go to: Alexey Starikovskiy, Meelis Roos , Nigel Cunningham , Pierre Ossman History of this bug is at: http://bugme.osdl.org/show_bug.cgi?id=4320 Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 2d8bf05..761956e 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -17,12 +17,12 @@ #include #include #include +#include #include "power.h" extern suspend_disk_method_t pm_disk_mode; -extern struct pm_ops * pm_ops; extern int swsusp_suspend(void); extern int swsusp_write(void); @@ -49,13 +49,11 @@ dev_t swsusp_resume_device; static void power_down(suspend_disk_method_t mode) { - unsigned long flags; int error = 0; - local_irq_save(flags); switch(mode) { case PM_DISK_PLATFORM: - device_shutdown(); + kernel_power_off_prepare(); error = pm_ops->enter(PM_SUSPEND_DISK); break; case PM_DISK_SHUTDOWN: -- cgit v0.10.2 From 89559a6119e9779c732fdc7aef5e175bf090dd69 Mon Sep 17 00:00:00 2001 From: Prasanna S Panchamukhi Date: Thu, 22 Sep 2005 21:43:47 -0700 Subject: [PATCH] Update maintainers list with the kprobes maintainers This patch updates the maintainers list with kprobes maintainers. Signed-of-by: Prasanna S Panchamukhi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 78aca12..7d1dd5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1402,6 +1402,18 @@ L: linux-kernel@vger.kernel.org L: fastboot@osdl.org S: Maintained +KPROBES +P: Prasanna S Panchamukhi +M: prasanna@in.ibm.com +P: Ananth N Mavinakayanahalli +M: ananth@in.ibm.com +P: Anil S Keshavamurthy +M: anil.s.keshavamurthy@intel.com +P: David S. Miller +M: davem@davemloft.net +L: linux-kernel@vger.kernel.org +S: Maintained + LANMEDIA WAN CARD DRIVER P: Andrew Stanley-Jones M: asj@lanmedia.com -- cgit v0.10.2 From d06a8fb130085c9f61e4c1a40445163087ecf89f Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Thu, 22 Sep 2005 21:43:48 -0700 Subject: [PATCH] v9fs: make conv functions to check for conv buffer overflow buf_check_size function checks if the conv buffer has enough space for the performed operation, but it doesn't return the result back to the calling function, only logs an error in the log. The report-back-error functionality was lost when buf_check_size was converted from macro to inline function. The return in the macro used to exit from the functions that include it, after the conversion it just exits from the inline function itself. The patch makes buf_check_size to return flag and all functions that use it check if they should perform the operation, or exit. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 1554731..ac2241d 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -3,6 +3,7 @@ * * 9P protocol conversion functions * + * Copyright (C) 2004, 2005 by Latchesar Ionkov * Copyright (C) 2004 by Eric Van Hensbergen * Copyright (C) 2002 by Ron Minnich * @@ -55,66 +56,70 @@ static inline int buf_check_overflow(struct cbuf *buf) return buf->p > buf->ep; } -static inline void buf_check_size(struct cbuf *buf, int len) +static inline int buf_check_size(struct cbuf *buf, int len) { if (buf->p+len > buf->ep) { if (buf->p < buf->ep) { eprintk(KERN_ERR, "buffer overflow\n"); buf->p = buf->ep + 1; + return 0; } } + + return 1; } static inline void *buf_alloc(struct cbuf *buf, int len) { void *ret = NULL; - buf_check_size(buf, len); - ret = buf->p; - buf->p += len; + if (buf_check_size(buf, len)) { + ret = buf->p; + buf->p += len; + } return ret; } static inline void buf_put_int8(struct cbuf *buf, u8 val) { - buf_check_size(buf, 1); - - buf->p[0] = val; - buf->p++; + if (buf_check_size(buf, 1)) { + buf->p[0] = val; + buf->p++; + } } static inline void buf_put_int16(struct cbuf *buf, u16 val) { - buf_check_size(buf, 2); - - *(__le16 *) buf->p = cpu_to_le16(val); - buf->p += 2; + if (buf_check_size(buf, 2)) { + *(__le16 *) buf->p = cpu_to_le16(val); + buf->p += 2; + } } static inline void buf_put_int32(struct cbuf *buf, u32 val) { - buf_check_size(buf, 4); - - *(__le32 *)buf->p = cpu_to_le32(val); - buf->p += 4; + if (buf_check_size(buf, 4)) { + *(__le32 *)buf->p = cpu_to_le32(val); + buf->p += 4; + } } static inline void buf_put_int64(struct cbuf *buf, u64 val) { - buf_check_size(buf, 8); - - *(__le64 *)buf->p = cpu_to_le64(val); - buf->p += 8; + if (buf_check_size(buf, 8)) { + *(__le64 *)buf->p = cpu_to_le64(val); + buf->p += 8; + } } static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) { - buf_check_size(buf, slen + 2); - - buf_put_int16(buf, slen); - memcpy(buf->p, s, slen); - buf->p += slen; + if (buf_check_size(buf, slen + 2)) { + buf_put_int16(buf, slen); + memcpy(buf->p, s, slen); + buf->p += slen; + } } static inline void buf_put_string(struct cbuf *buf, const char *s) @@ -124,20 +129,20 @@ static inline void buf_put_string(struct cbuf *buf, const char *s) static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen) { - buf_check_size(buf, datalen); - - memcpy(buf->p, data, datalen); - buf->p += datalen; + if (buf_check_size(buf, datalen)) { + memcpy(buf->p, data, datalen); + buf->p += datalen; + } } static inline u8 buf_get_int8(struct cbuf *buf) { u8 ret = 0; - buf_check_size(buf, 1); - ret = buf->p[0]; - - buf->p++; + if (buf_check_size(buf, 1)) { + ret = buf->p[0]; + buf->p++; + } return ret; } @@ -146,10 +151,10 @@ static inline u16 buf_get_int16(struct cbuf *buf) { u16 ret = 0; - buf_check_size(buf, 2); - ret = le16_to_cpu(*(__le16 *)buf->p); - - buf->p += 2; + if (buf_check_size(buf, 2)) { + ret = le16_to_cpu(*(__le16 *)buf->p); + buf->p += 2; + } return ret; } @@ -158,10 +163,10 @@ static inline u32 buf_get_int32(struct cbuf *buf) { u32 ret = 0; - buf_check_size(buf, 4); - ret = le32_to_cpu(*(__le32 *)buf->p); - - buf->p += 4; + if (buf_check_size(buf, 4)) { + ret = le32_to_cpu(*(__le32 *)buf->p); + buf->p += 4; + } return ret; } @@ -170,10 +175,10 @@ static inline u64 buf_get_int64(struct cbuf *buf) { u64 ret = 0; - buf_check_size(buf, 8); - ret = le64_to_cpu(*(__le64 *)buf->p); - - buf->p += 8; + if (buf_check_size(buf, 8)) { + ret = le64_to_cpu(*(__le64 *)buf->p); + buf->p += 8; + } return ret; } @@ -181,27 +186,35 @@ static inline u64 buf_get_int64(struct cbuf *buf) static inline int buf_get_string(struct cbuf *buf, char *data, unsigned int datalen) { + u16 len = 0; + + len = buf_get_int16(buf); + if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) { + memcpy(data, buf->p, len); + data[len] = 0; + buf->p += len; + len++; + } - u16 len = buf_get_int16(buf); - buf_check_size(buf, len); - if (len + 1 > datalen) - return 0; - - memcpy(data, buf->p, len); - data[len] = 0; - buf->p += len; - - return len + 1; + return len; } static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) { - char *ret = NULL; - int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p); + char *ret; + u16 len; + + ret = NULL; + len = buf_get_int16(buf); - if (n > 0) { + if (!buf_check_overflow(buf) && buf_check_size(buf, len) && + buf_check_size(sbuf, len+1)) { + + memcpy(sbuf->p, buf->p, len); + sbuf->p[len] = 0; ret = sbuf->p; - sbuf->p += n; + buf->p += len; + sbuf->p += len + 1; } return ret; @@ -209,12 +222,15 @@ static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) static inline int buf_get_data(struct cbuf *buf, void *data, int datalen) { - buf_check_size(buf, datalen); + int ret = 0; - memcpy(data, buf->p, datalen); - buf->p += datalen; + if (buf_check_size(buf, datalen)) { + memcpy(data, buf->p, datalen); + buf->p += datalen; + ret = datalen; + } - return datalen; + return ret; } static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, @@ -223,13 +239,12 @@ static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, char *ret = NULL; int n = 0; - buf_check_size(dbuf, datalen); - - n = buf_get_data(buf, dbuf->p, datalen); - - if (n > 0) { - ret = dbuf->p; - dbuf->p += n; + if (buf_check_size(dbuf, datalen)) { + n = buf_get_data(buf, dbuf->p, datalen); + if (n > 0) { + ret = dbuf->p; + dbuf->p += n; + } } return ret; -- cgit v0.10.2 From 5b067676234715051cbde87083c36c8ea83f77b8 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Thu, 22 Sep 2005 21:43:50 -0700 Subject: [PATCH] v9fs: allocate the Rwalk qid array from the right conv buffer When v9fs_deserealize_fcall deserializes a Rwalk message, it incorrectly allocates space for the qid array in the source instead of the destination buffer. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/conv.c b/fs/9p/conv.c index ac2241d..18121af 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -651,7 +651,7 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, break; case RWALK: rcall->params.rwalk.nwqid = buf_get_int16(bufp); - rcall->params.rwalk.wqids = buf_alloc(bufp, + rcall->params.rwalk.wqids = buf_alloc(dbufp, rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); if (rcall->params.rwalk.wqids) for (i = 0; i < rcall->params.rwalk.nwqid; i++) { -- cgit v0.10.2 From a8e63bff521f0387fb4f4e486dede0e78dca8f41 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Thu, 22 Sep 2005 21:43:51 -0700 Subject: [PATCH] v9fs: make copy of the transport prototype instead of using it directly When a new session is created it uses a template object of the specified transport type to instantiate its own copy. The code for the making a copy of the template object was lost, and the object itself is attached to the v9fs session. This leads to many sessions using the same transport instead of having their own copy. The patch puts back the code that makes a copy of the template object. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 13bdbba..82303f3 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -303,7 +303,13 @@ v9fs_session_init(struct v9fs_session_info *v9ses, goto SessCleanUp; }; - v9ses->transport = trans_proto; + v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); + if (!v9ses->transport) { + retval = -ENOMEM; + goto SessCleanUp; + } + + memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { eprintk(KERN_ERR, "problem initializing transport\n"); -- cgit v0.10.2 From a1f9d8d23fef301ba0c0b4983e0aa947168e1c37 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Thu, 22 Sep 2005 21:43:52 -0700 Subject: [PATCH] v9fs: replace strlen on newly allocated by __getname buffers to PATH_MAX v9fs_vfs_readlink allocates space for the link using __getname and errorneously uses strlen on the newly allocated buffer to check if the buffer passed by the user is bigger than the one returned by __getname. The patch replaces the strlen usage to PATH_MAX, which is the actual size of the buffers returned by __getname. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 0c13fc6..b16322d 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1063,8 +1063,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, int ret; char *link = __getname(); - if (strlen(link) < buflen) - buflen = strlen(link); + if (buflen > PATH_MAX) + buflen = PATH_MAX; dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); -- cgit v0.10.2 From f71626a461e7d4af099ca71830ea530e96c22e11 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Thu, 22 Sep 2005 21:43:53 -0700 Subject: [PATCH] v9fs: don't free root dentry & inode if error occurs in v9fs_get_sb If error occurs while in v9fs_get_sb after it calles sget, the dentry object of the root and its inode may be freed twice -- once while handling the error in v9fs_get_sb, and second time when v9fs_get_sb calles deactivate_super (which in turn calls v9fs_kill_super) The patch removes the unnecessary code that frees the root dentry and its inode. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 868f350..1e2b2b5 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -129,8 +129,8 @@ static struct super_block *v9fs_get_sb(struct file_system_type if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); - retval = newfid; - goto free_session; + kfree(v9ses); + return ERR_PTR(newfid); } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); @@ -150,7 +150,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type if (!root) { retval = -ENOMEM; - goto release_inode; + goto put_back_sb; } sb->s_root = root; @@ -159,7 +159,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type root_fid = v9fs_fid_create(root); if (root_fid == NULL) { retval = -ENOMEM; - goto release_dentry; + goto put_back_sb; } root_fid->fidopen = 0; @@ -182,25 +182,15 @@ static struct super_block *v9fs_get_sb(struct file_system_type if (stat_result < 0) { retval = stat_result; - goto release_dentry; + goto put_back_sb; } return sb; - release_dentry: - dput(sb->s_root); - - release_inode: - iput(inode); - - put_back_sb: +put_back_sb: + /* deactivate_super calls v9fs_kill_super which will frees the rest */ up_write(&sb->s_umount); deactivate_super(sb); - v9fs_session_close(v9ses); - - free_session: - kfree(v9ses); - return ERR_PTR(retval); } -- cgit v0.10.2 From e1e70a262d5cb5a02d2fc171e0178197849482d4 Mon Sep 17 00:00:00 2001 From: Bernd Petrovitsch Date: Thu, 22 Sep 2005 21:43:53 -0700 Subject: [PATCH] Rename vprintk define in bttpvp.h Rename the (apparently) bttv intern #define vprintk to verbprintk to resolve a name clash. Reason: vprintk() is defined in include/linux/kernel.h similar to printk but with a va_list argument. (akpm: I changed it to bttv_printk) Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index a564321..c062a01 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -763,21 +763,21 @@ static void set_pll(struct bttv *btv) /* no PLL needed */ if (btv->pll.pll_current == 0) return; - vprintk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n", - btv->c.nr,btv->pll.pll_ifreq); + bttv_printk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n", + btv->c.nr,btv->pll.pll_ifreq); btwrite(0x00,BT848_TGCTRL); btwrite(0x00,BT848_PLL_XCI); btv->pll.pll_current = 0; return; } - vprintk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr, - btv->pll.pll_ifreq, btv->pll.pll_ofreq); + bttv_printk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr, + btv->pll.pll_ifreq, btv->pll.pll_ofreq); set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); for (i=0; i<10; i++) { /* Let other people run while the PLL stabilizes */ - vprintk("."); + bttv_printk("."); msleep(10); if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) { @@ -785,12 +785,12 @@ static void set_pll(struct bttv *btv) } else { btwrite(0x08,BT848_TGCTRL); btv->pll.pll_current = btv->pll.pll_ofreq; - vprintk(" ok\n"); + bttv_printk(" ok\n"); return; } } btv->pll.pll_current = -1; - vprintk("failed\n"); + bttv_printk("failed\n"); return; } diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 9b0b7ca..7a312f7 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -221,7 +221,7 @@ extern void bttv_gpio_tracking(struct bttv *btv, char *comment); extern int init_bttv_i2c(struct bttv *btv); extern int fini_bttv_i2c(struct bttv *btv); -#define vprintk if (bttv_verbose) printk +#define bttv_printk if (bttv_verbose) printk #define dprintk if (bttv_debug >= 1) printk #define d2printk if (bttv_debug >= 2) printk -- cgit v0.10.2 From 66c81f0059b57e18aad43a5b0d330102c237cd72 Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Thu, 22 Sep 2005 21:43:54 -0700 Subject: [PATCH] DEBUG redefined in drivers/mtd/devices/docecc.c Fix namespace clash: drivers/mtd/devices/docecc.c:43:1: warning: "DEBUG" redefined In file included from drivers/mtd/devices/docecc.c:40: include/linux/mtd/mtd.h:219:1: warning: this is the location of the previous definition Signed-off-by: Grant Coady Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 9a087c1..24f670b 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c @@ -40,7 +40,7 @@ #include #include -#define DEBUG 0 +#define DEBUG_ECC 0 /* need to undef it (from asm/termbits.h) */ #undef B0 @@ -249,7 +249,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], lambda[j] ^= Alpha_to[modnn(u + tmp)]; } } -#if DEBUG >= 1 +#if DEBUG_ECC >= 1 /* Test code that verifies the erasure locator polynomial just constructed Needed only for decoder debugging. */ @@ -276,7 +276,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], count = -1; goto finish; } -#if DEBUG >= 2 +#if DEBUG_ECC >= 2 printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); for (i = 0; i < count; i++) printf("%d ", loc[i]); @@ -409,7 +409,7 @@ eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])]; } if (den == 0) { -#if DEBUG >= 1 +#if DEBUG_ECC >= 1 printf("\n ERROR: denominator = 0\n"); #endif /* Convert to dual- basis */ -- cgit v0.10.2 From 244bc050d5c9431682b7d834aff92e663fe88bb2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 22 Sep 2005 21:43:55 -0700 Subject: [PATCH] ppc32: fix build with oprofile Current -git tree doesn't build when enabling oprofile on a non-bookE CPU (like on a PowerMac for example). While there is no performance counter support for these CPUs implemented yet, it's still nice to be able to use the timer based sampling, and that got broken. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 1fb92f1..b1457a8 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,9 +15,8 @@ extra-y += vmlinux.lds obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ semaphore.o syscalls.o setup.o \ - cputable.o ppc_htab.o + cputable.o ppc_htab.o perfmon.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o -obj-$(CONFIG_E500) += perfmon.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c index fa1dad9..04c1878 100644 --- a/arch/ppc/kernel/perfmon.c +++ b/arch/ppc/kernel/perfmon.c @@ -45,7 +45,7 @@ static void dummy_perf(struct pt_regs *regs) mtpmr(PMRN_PMGC0, pmgc0); } -#else +#elif CONFIG_6xx /* Ensure exceptions are disabled */ static void dummy_perf(struct pt_regs *regs) @@ -55,6 +55,10 @@ static void dummy_perf(struct pt_regs *regs) mmcr0 &= ~MMCR0_PMXE; mtspr(SPRN_MMCR0, mmcr0); } +#else +static void dummy_perf(struct pt_regs *regs) +{ +} #endif void (*perf_irq)(struct pt_regs *) = dummy_perf; -- cgit v0.10.2 From 720b9429e8f41f7c4ee9df293403650905042035 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 22 Sep 2005 21:43:56 -0700 Subject: [PATCH] SOFTWARE_SUSPEND needs HOTPLUG_CPU on SMP Signed-off-by: Randy Dunlap Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 396c787..46a5e5a 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -29,7 +29,7 @@ config PM_DEBUG config SOFTWARE_SUSPEND bool "Software Suspend" - depends on PM && SWAP && (X86 || ((FVR || PPC32) && !SMP)) + depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FVR || PPC32) && !SMP) ---help--- Enable the possibility of suspending the machine. It doesn't need APM. -- cgit v0.10.2 From 4b3c86a7452df8608c32a1c1f19c0cc0723c145f Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Thu, 22 Sep 2005 21:43:57 -0700 Subject: [PATCH] alpha: fix kernel panic during SysRq-b acquire_console_sem() does BUG() in interrupt context now, as in the case of SysRq-b. Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index fa98dae..eb20c3a 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -127,6 +127,10 @@ common_shutdown_1(void *generic_ptr) /* If booted from SRM, reset some of the original environment. */ if (alpha_using_srm) { #ifdef CONFIG_DUMMY_CONSOLE + /* If we've gotten here after SysRq-b, leave interrupt + context before taking over the console. */ + if (in_interrupt()) + irq_exit(); /* This has the effect of resetting the VGA video origin. */ take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1); #endif -- cgit v0.10.2 From 7243cc05bafdda4c4de77cba00cf87666bd237f7 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Thu, 22 Sep 2005 21:43:58 -0700 Subject: [PATCH] slab: alpha inlining fix It is essential that index_of() be inlined. But alpha undoes the gcc inlining hackery and index_of() ends up out-of-line. So fiddle with things to make that function inline again. Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-alpha/compiler.h b/include/asm-alpha/compiler.h index 399c33b..0a4a8b4 100644 --- a/include/asm-alpha/compiler.h +++ b/include/asm-alpha/compiler.h @@ -98,6 +98,9 @@ #undef inline #undef __inline__ #undef __inline - +#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3 +#undef __always_inline +#define __always_inline inline __attribute__((always_inline)) +#endif #endif /* __ALPHA_COMPILER_H */ diff --git a/mm/slab.c b/mm/slab.c index 437d338..cf19ff2 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -308,12 +308,12 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS]; #define SIZE_L3 (1 + MAX_NUMNODES) /* - * This function may be completely optimized away if + * This function must be completely optimized away if * a constant is passed to it. Mostly the same as * what is in linux/slab.h except it returns an * index. */ -static inline int index_of(const size_t size) +static __always_inline int index_of(const size_t size) { if (__builtin_constant_p(size)) { int i = 0; @@ -329,7 +329,8 @@ static inline int index_of(const size_t size) extern void __bad_size(void); __bad_size(); } - } + } else + BUG(); return 0; } -- cgit v0.10.2 From 609725f87709724218047a1049913ed233f79d3c Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 22 Sep 2005 21:43:59 -0700 Subject: [PATCH] Fix mmap() of /dev/hpet The address passed to io_remap_pfn_range() in hpet_mmap() does not need to be converted using __pa(): it is already a physical address. This bug was found and the patch suggested by Clay Harris. I introduced this particular bug when making io_remap_pfn_range changes a few months ago. In fact mmap()ing /dev/hpet has *never* previously worked: before my changes __pa() was being executed on an ioremap()ed virtual address, which is also invalid. Signed-off-by: Keir Fraser Cc: Robert Picco Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index de0379b..c055bb6 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -273,7 +273,6 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - addr = __pa(addr); if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) { -- cgit v0.10.2 From 4c87b74c72d42f7272aa4bf8f17c73bb53774eee Mon Sep 17 00:00:00 2001 From: Robert Love Date: Thu, 22 Sep 2005 21:44:00 -0700 Subject: [PATCH] hdaps: small update. - Handle dmi_system_check() elegantly, now that my bugfix is upstream. - Add support for the X41 and R52. - Cleanup some comments do I do not have to keep updating them with each new whitelisted laptop. Signed-off-by: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 7e72e92..db358cf 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -418,12 +418,11 @@ config SENSORS_HDAPS help This driver provides support for the IBM Hard Drive Active Protection System (hdaps), which provides an accelerometer and other misc. data. - Supported laptops include the IBM ThinkPad T41, T42, T43, and R51. - The accelerometer data is readable via sysfs. + ThinkPads starting with the R50, T41, and X40 are supported. The + accelerometer data is readable via sysfs. - This driver also provides an input class device, allowing the - laptop to act as a pinball machine-esque mouse. This is off by - default but enabled via sysfs or the module parameter "mousedev". + This driver also provides an absolute input class device, allowing + the laptop to act as a pinball machine-esque joystick. Say Y here if you have an applicable laptop and want to experience the awesome power of hdaps. diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 4c56411..7f01076 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -4,9 +4,9 @@ * Copyright (C) 2005 Robert Love * Copyright (C) 2005 Jesper Juhl * - * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad - * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic - * two-axis accelerometer and other data, such as the device's temperature. + * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads + * starting with the R40, T41, and X40. It provides a basic two-axis + * accelerometer and other data, such as the device's temperature. * * This driver is based on the document by Mark A. Smith available at * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial @@ -487,24 +487,19 @@ static struct attribute_group hdaps_attribute_group = { /* Module stuff */ -/* - * XXX: We should be able to return nonzero and halt the detection process. - * But there is a bug in dmi_check_system() where a nonzero return from the - * first match will result in a return of failure from dmi_check_system(). - * I fixed this; the patch is 2.6-git. Once in a released tree, we can make - * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. - */ +/* hdaps_dmi_match - found a match. return one, short-circuiting the hunt. */ static int hdaps_dmi_match(struct dmi_system_id *id) { printk(KERN_INFO "hdaps: %s detected.\n", id->ident); - return 0; + return 1; } +/* hdaps_dmi_match_invert - found an inverted match. */ static int hdaps_dmi_match_invert(struct dmi_system_id *id) { hdaps_invert = 1; printk(KERN_INFO "hdaps: inverting axis readings.\n"); - return 0; + return hdaps_dmi_match(id); } #define HDAPS_DMI_MATCH_NORMAL(model) { \ @@ -534,6 +529,7 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"), HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"), HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"), @@ -541,6 +537,7 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), + HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"), { .ident = NULL } }; -- cgit v0.10.2 From 57487f4376e16558ccbe45a5b41d8cb5192309a4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 22 Sep 2005 21:44:01 -0700 Subject: [PATCH] swsusp: do not trigger BUG_ON() if there is not enough memory The following patch makes swsusp avoid triggering the BUG_ON() in swsusp_suspend() if there is not enough memory for suspend. Signed-off-by: Rafael J. Wysocki Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index d967e87..353f37f 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -918,6 +918,7 @@ static int swsusp_alloc(void) pagedir_nosave = NULL; nr_copy_pages = calc_nr(nr_copy_pages); + nr_copy_pages_check = nr_copy_pages; pr_debug("suspend: (pages needed: %d + %d free: %d)\n", nr_copy_pages, PAGES_FOR_IO, nr_free_pages()); @@ -940,7 +941,6 @@ static int swsusp_alloc(void) return error; } - nr_copy_pages_check = nr_copy_pages; return 0; } -- cgit v0.10.2 From ff69416e6323fe9d38c42a06ebdefeb58bbe9336 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 22 Sep 2005 21:44:02 -0700 Subject: [PATCH] slab: fix handling of pages from foreign NUMA nodes The numa slab allocator may allocate pages from foreign nodes onto the lists for a particular node if a node runs out of memory. Inspecting the slab->nodeid field will not reflect that the page is now in use for the slabs of another node. This patch fixes that issue by adding a node field to free_block so that the caller can indicate which node currently uses a slab. Also removes the check for the current node from kmalloc_cache_node since the process may shift later to another node which may lead to an allocation on another node than intended. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index cf19ff2..c9adfce 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -640,7 +640,7 @@ static enum { static DEFINE_PER_CPU(struct work_struct, reap_work); -static void free_block(kmem_cache_t* cachep, void** objpp, int len); +static void free_block(kmem_cache_t* cachep, void** objpp, int len, int node); static void enable_cpucache (kmem_cache_t *cachep); static void cache_reap (void *unused); static int __node_shrink(kmem_cache_t *cachep, int node); @@ -805,7 +805,7 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache if (ac->avail) { spin_lock(&rl3->list_lock); - free_block(cachep, ac->entry, ac->avail); + free_block(cachep, ac->entry, ac->avail, node); ac->avail = 0; spin_unlock(&rl3->list_lock); } @@ -926,7 +926,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, /* Free limit for this kmem_list3 */ l3->free_limit -= cachep->batchcount; if (nc) - free_block(cachep, nc->entry, nc->avail); + free_block(cachep, nc->entry, nc->avail, node); if (!cpus_empty(mask)) { spin_unlock(&l3->list_lock); @@ -935,7 +935,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, if (l3->shared) { free_block(cachep, l3->shared->entry, - l3->shared->avail); + l3->shared->avail, node); kfree(l3->shared); l3->shared = NULL; } @@ -1883,12 +1883,13 @@ static void do_drain(void *arg) { kmem_cache_t *cachep = (kmem_cache_t*)arg; struct array_cache *ac; + int node = numa_node_id(); check_irq_off(); ac = ac_data(cachep); - spin_lock(&cachep->nodelists[numa_node_id()]->list_lock); - free_block(cachep, ac->entry, ac->avail); - spin_unlock(&cachep->nodelists[numa_node_id()]->list_lock); + spin_lock(&cachep->nodelists[node]->list_lock); + free_block(cachep, ac->entry, ac->avail, node); + spin_unlock(&cachep->nodelists[node]->list_lock); ac->avail = 0; } @@ -2609,7 +2610,7 @@ done: /* * Caller needs to acquire correct kmem_list's list_lock */ -static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects) +static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int node) { int i; struct kmem_list3 *l3; @@ -2618,14 +2619,12 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects) void *objp = objpp[i]; struct slab *slabp; unsigned int objnr; - int nodeid = 0; slabp = GET_PAGE_SLAB(virt_to_page(objp)); - nodeid = slabp->nodeid; - l3 = cachep->nodelists[nodeid]; + l3 = cachep->nodelists[node]; list_del(&slabp->list); objnr = (objp - slabp->s_mem) / cachep->objsize; - check_spinlock_acquired_node(cachep, nodeid); + check_spinlock_acquired_node(cachep, node); check_slabp(cachep, slabp); @@ -2665,13 +2664,14 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac) { int batchcount; struct kmem_list3 *l3; + int node = numa_node_id(); batchcount = ac->batchcount; #if DEBUG BUG_ON(!batchcount || batchcount > ac->avail); #endif check_irq_off(); - l3 = cachep->nodelists[numa_node_id()]; + l3 = cachep->nodelists[node]; spin_lock(&l3->list_lock); if (l3->shared) { struct array_cache *shared_array = l3->shared; @@ -2687,7 +2687,7 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac) } } - free_block(cachep, ac->entry, batchcount); + free_block(cachep, ac->entry, batchcount, node); free_done: #if STATS { @@ -2752,7 +2752,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) } else { spin_lock(&(cachep->nodelists[nodeid])-> list_lock); - free_block(cachep, &objp, 1); + free_block(cachep, &objp, 1, nodeid); spin_unlock(&(cachep->nodelists[nodeid])-> list_lock); } @@ -2845,7 +2845,7 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i unsigned long save_flags; void *ptr; - if (nodeid == numa_node_id() || nodeid == -1) + if (nodeid == -1) return __cache_alloc(cachep, flags); if (unlikely(!cachep->nodelists[nodeid])) { @@ -3080,7 +3080,7 @@ static int alloc_kmemlist(kmem_cache_t *cachep) if ((nc = cachep->nodelists[node]->shared)) free_block(cachep, nc->entry, - nc->avail); + nc->avail, node); l3->shared = new; if (!cachep->nodelists[node]->alien) { @@ -3161,7 +3161,7 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount, if (!ccold) continue; spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock); - free_block(cachep, ccold->entry, ccold->avail); + free_block(cachep, ccold->entry, ccold->avail, cpu_to_node(i)); spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock); kfree(ccold); } @@ -3241,7 +3241,7 @@ static void drain_array_locked(kmem_cache_t *cachep, if (tofree > ac->avail) { tofree = (ac->avail+1)/2; } - free_block(cachep, ac->entry, tofree); + free_block(cachep, ac->entry, tofree, node); ac->avail -= tofree; memmove(ac->entry, &(ac->entry[tofree]), sizeof(void*)*ac->avail); -- cgit v0.10.2 From 275abf5b06676ca057cf3e15f0d027eafcb204a0 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Thu, 22 Sep 2005 21:44:03 -0700 Subject: [PATCH] ext3: ext3_show_options fix EXT3_MOUNT_DATA_FLAGS is not a boolean. This fixes it. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ext3/super.c b/fs/ext3/super.c index a93c360..9e24ceb 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -512,15 +512,14 @@ static void ext3_clear_inode(struct inode *inode) static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) { - struct ext3_sb_info *sbi = EXT3_SB(vfs->mnt_sb); + struct super_block *sb = vfs->mnt_sb; + struct ext3_sb_info *sbi = EXT3_SB(sb); - if (sbi->s_mount_opt & EXT3_MOUNT_JOURNAL_DATA) + if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA) seq_puts(seq, ",data=journal"); - - if (sbi->s_mount_opt & EXT3_MOUNT_ORDERED_DATA) + else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA) seq_puts(seq, ",data=ordered"); - - if (sbi->s_mount_opt & EXT3_MOUNT_WRITEBACK_DATA) + else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) seq_puts(seq, ",data=writeback"); #if defined(CONFIG_QUOTA) -- cgit v0.10.2 From 586a90eb4c0b512df766e08a7718af7c6b9b2dcf Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 22 Sep 2005 21:44:04 -0700 Subject: [PATCH] ppc64: Fix LPAR regression The recent iommu fix broke booting on some POWER4 and POWER5 LPAR boxes. It looks like we have been calling the non LPAR iommu_dev_setup on LPAR machines for a while. The recent iommu fix caused that code path to fail. It looks like we just need to hook up the devices iommu_table to the parents one, so do that instead of calling iommu_dev_setup_pSeries and crossing the streams. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index 8c6313e..25d6c7e 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -525,9 +525,8 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) * slots on POWER4 machines. */ if (dma_window == NULL || pdn->parent == NULL) { - /* Fall back to regular (non-LPAR) dev setup */ - DBG("No dma window for device, falling back to regular setup\n"); - iommu_dev_setup_pSeries(dev); + DBG("No dma window for device, linking to parent\n"); + PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; return; } else { DBG("Found DMA window, allocating table\n"); -- cgit v0.10.2 From f951da3757cf46444a6ea52e97b8aa9400fe761a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 22 Sep 2005 21:44:05 -0700 Subject: [PATCH] ppc64: Fix build with iommu debug enabled Fix build when iommu debug is enabled. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index 25d6c7e..d17f010 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c @@ -364,7 +364,8 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) while (pci->phb->dma_window_size * children > 0x80000000ul) pci->phb->dma_window_size >>= 1; - DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + DBG("No ISA/IDE, window size is 0x%lx\n", + pci->phb->dma_window_size); pci->phb->dma_window_base_cur = 0; return; @@ -388,7 +389,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) while (pci->phb->dma_window_size * children > 0x70000000ul) pci->phb->dma_window_size >>= 1; - DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); + DBG("ISA/IDE, window size is 0x%lx\n", pci->phb->dma_window_size); } @@ -442,7 +443,7 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) struct device_node *dn, *mydn; struct iommu_table *tbl; - DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); + DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); mydn = dn = pci_device_to_OF_node(dev); @@ -469,7 +470,7 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) if (dn && dn->data) { PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; } else { - DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name); + DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); } } @@ -503,7 +504,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) int *dma_window = NULL; struct pci_dn *pci; - DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name); + DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); /* dev setup for LPAR is a little tricky, since the device tree might * contain the dma-window properties per-device and not neccesarily -- cgit v0.10.2 From 0f329075fb1dbd6845db03e9bb8252024fdbea1f Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 22 Sep 2005 21:44:05 -0700 Subject: [PATCH] ppc64: Fix 64bit ptrace DABR support Fix my stupid bug in the 64bit version of PTRACE_SET_DEBUGREG. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index 85ed318..b1c044c 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -219,6 +219,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SET_DEBUGREG: ret = ptrace_set_debugreg(child, addr, data); + break; case PTRACE_DETACH: ret = ptrace_detach(child, data); -- cgit v0.10.2 From 0365ba7fb1fa94a41289d6a3d36b4d95960e56cc Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 22 Sep 2005 21:44:06 -0700 Subject: [PATCH] ppc64: SMU driver update & i2c support The SMU is the "system controller" chip used by Apple recent G5 machines including the iMac G5. It drives things like fans, i2c busses, real time clock, etc... The current kernel contains a very crude driver that doesn't do much more than reading the real time clock synchronously. This is a completely rewritten driver that provides interrupt based command queuing, a userland interface, and an i2c/smbus driver for accessing the devices hanging off the SMU i2c busses like temperature sensors. This driver is a basic block for upcoming work on thermal control for those machines, among others. Signed-off-by: Benjamin Herrenschmidt Cc: Jean Delvare Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index b392b9a..4c56a47 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -719,7 +719,8 @@ pmac_declare_of_platform_devices(void) if (np) { for (np = np->child; np != NULL; np = np->sibling) if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "uni-n-i2c"); + of_platform_device_create(np, "uni-n-i2c", + NULL); break; } } @@ -727,17 +728,18 @@ pmac_declare_of_platform_devices(void) if (np) { for (np = np->child; np != NULL; np = np->sibling) if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "u3-i2c"); + of_platform_device_create(np, "u3-i2c", + NULL); break; } } np = find_devices("valkyrie"); if (np) - of_platform_device_create(np, "valkyrie"); + of_platform_device_create(np, "valkyrie", NULL); np = find_devices("platinum"); if (np) - of_platform_device_create(np, "platinum"); + of_platform_device_create(np, "platinum", NULL); return 0; } diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c index da8a0f2..93c7231 100644 --- a/arch/ppc/syslib/of_device.c +++ b/arch/ppc/syslib/of_device.c @@ -234,7 +234,9 @@ void of_device_unregister(struct of_device *ofdev) device_unregister(&ofdev->dev); } -struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) { struct of_device *dev; u32 *reg; @@ -247,7 +249,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char * dev->node = of_node_get(np); dev->dma_mask = 0xffffffffUL; dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = NULL; + dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; dev->dev.release = of_release_dev; diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c index da58081..9f200f0 100644 --- a/arch/ppc64/kernel/of_device.c +++ b/arch/ppc64/kernel/of_device.c @@ -233,7 +233,9 @@ void of_device_unregister(struct of_device *ofdev) device_unregister(&ofdev->dev); } -struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) { struct of_device *dev; @@ -245,7 +247,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char * dev->node = np; dev->dma_mask = 0xffffffffUL; dev->dev.dma_mask = &dev->dma_mask; - dev->dev.parent = NULL; + dev->dev.parent = parent; dev->dev.bus = &of_platform_bus_type; dev->dev.release = of_release_dev; @@ -259,6 +261,7 @@ struct of_device* of_platform_device_create(struct device_node *np, const char * return dev; } + EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_platform_bus_type); EXPORT_SYMBOL(of_register_driver); diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index 325426c..2575525 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -434,15 +434,23 @@ static int pmac_check_legacy_ioport(unsigned int baseport) static int __init pmac_declare_of_platform_devices(void) { - struct device_node *np; + struct device_node *np, *npp; - np = find_devices("u3"); - if (np) { - for (np = np->child; np != NULL; np = np->sibling) + npp = of_find_node_by_name(NULL, "u3"); + if (npp) { + for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) { if (strncmp(np->name, "i2c", 3) == 0) { - of_platform_device_create(np, "u3-i2c"); + of_platform_device_create(np, "u3-i2c", NULL); + of_node_put(np); break; } + } + of_node_put(npp); + } + npp = of_find_node_by_type(NULL, "smu"); + if (npp) { + of_platform_device_create(npp, "smu", NULL); + of_node_put(npp); } return 0; diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c index 3059edb..41bbb8c 100644 --- a/arch/ppc64/kernel/pmac_time.c +++ b/arch/ppc64/kernel/pmac_time.c @@ -84,7 +84,7 @@ void __pmac pmac_get_rtc_time(struct rtc_time *tm) #ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: - smu_get_rtc_time(tm); + smu_get_rtc_time(tm, 1); break; #endif /* CONFIG_PMAC_SMU */ default: @@ -128,7 +128,7 @@ int __pmac pmac_set_rtc_time(struct rtc_time *tm) #ifdef CONFIG_PMAC_SMU case SYS_CTRLER_SMU: - return smu_set_rtc_time(tm); + return smu_set_rtc_time(tm, 1); #endif /* CONFIG_PMAC_SMU */ default: return -ENODEV; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 8334496..3badfec 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -245,6 +245,18 @@ config I2C_KEYWEST This support is also available as a module. If so, the module will be called i2c-keywest. +config I2C_PMAC_SMU + tristate "Powermac SMU I2C interface" + depends on I2C && PMAC_SMU + help + This supports the use of the I2C interface in the SMU + chip on recent Apple machines like the iMac G5. It is used + among others by the thermal control driver for those machines. + Say Y if you have such a machine. + + This support is also available as a module. If so, the module + will be called i2c-pmac-smu. + config I2C_MPC tristate "MPC107/824x/85xx/52xx" depends on I2C && PPC32 diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 980b3e9..f1df00f 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_I2C_ITE) += i2c-ite.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o +obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c new file mode 100644 index 0000000..8a9f564 --- /dev/null +++ b/drivers/i2c/busses/i2c-pmac-smu.c @@ -0,0 +1,316 @@ +/* + i2c Support for Apple SMU Controller + + Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp. + + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int probe; + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("I2C driver for Apple's SMU"); +MODULE_LICENSE("GPL"); +module_param(probe, bool, 0); + + +/* Physical interface */ +struct smu_iface +{ + struct i2c_adapter adapter; + struct completion complete; + u32 busid; +}; + +static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc) +{ + struct smu_iface *iface = misc; + complete(&iface->complete); +} + +/* + * SMBUS-type transfer entrypoint + */ +static s32 smu_smbus_xfer( struct i2c_adapter* adap, + u16 addr, + unsigned short flags, + char read_write, + u8 command, + int size, + union i2c_smbus_data* data) +{ + struct smu_iface *iface = i2c_get_adapdata(adap); + struct smu_i2c_cmd cmd; + int rc = 0; + int read = (read_write == I2C_SMBUS_READ); + + cmd.info.bus = iface->busid; + cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00); + + /* Prepare datas & select mode */ + switch (size) { + case I2C_SMBUS_QUICK: + cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; + cmd.info.datalen = 0; + break; + case I2C_SMBUS_BYTE: + cmd.info.type = SMU_I2C_TRANSFER_SIMPLE; + cmd.info.datalen = 1; + if (!read) + cmd.info.data[0] = data->byte; + break; + case I2C_SMBUS_BYTE_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = 1; + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + if (!read) + cmd.info.data[0] = data->byte; + break; + case I2C_SMBUS_WORD_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = 2; + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + if (!read) { + cmd.info.data[0] = data->byte & 0xff; + cmd.info.data[1] = (data->byte >> 8) & 0xff; + } + break; + /* Note that these are broken vs. the expected smbus API where + * on reads, the lenght is actually returned from the function, + * but I think the current API makes no sense and I don't want + * any driver that I haven't verified for correctness to go + * anywhere near a pmac i2c bus anyway ... + */ + case I2C_SMBUS_BLOCK_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = data->block[0] + 1; + if (cmd.info.datalen > 6) + return -EINVAL; + if (!read) + memcpy(cmd.info.data, data->block, cmd.info.datalen); + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + cmd.info.type = SMU_I2C_TRANSFER_STDSUB; + cmd.info.datalen = data->block[0]; + if (cmd.info.datalen > 7) + return -EINVAL; + if (!read) + memcpy(cmd.info.data, &data->block[1], + cmd.info.datalen); + cmd.info.sublen = 1; + cmd.info.subaddr[0] = command; + cmd.info.subaddr[1] = 0; + cmd.info.subaddr[2] = 0; + break; + + default: + return -EINVAL; + } + + /* Turn a standardsub read into a combined mode access */ + if (read_write == I2C_SMBUS_READ && + cmd.info.type == SMU_I2C_TRANSFER_STDSUB) + cmd.info.type = SMU_I2C_TRANSFER_COMBINED; + + /* Finish filling command and submit it */ + cmd.done = smu_i2c_done; + cmd.misc = iface; + rc = smu_queue_i2c(&cmd); + if (rc < 0) + return rc; + wait_for_completion(&iface->complete); + rc = cmd.status; + + if (!read || rc < 0) + return rc; + + switch (size) { + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + data->byte = cmd.info.data[0]; + break; + case I2C_SMBUS_WORD_DATA: + data->word = ((u16)cmd.info.data[1]) << 8; + data->word |= cmd.info.data[0]; + break; + /* Note that these are broken vs. the expected smbus API where + * on reads, the lenght is actually returned from the function, + * but I think the current API makes no sense and I don't want + * any driver that I haven't verified for correctness to go + * anywhere near a pmac i2c bus anyway ... + */ + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + memcpy(&data->block[0], cmd.info.data, cmd.info.datalen); + break; + } + + return rc; +} + +static u32 +smu_smbus_func(struct i2c_adapter * adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +/* For now, we only handle combined mode (smbus) */ +static struct i2c_algorithm smu_algorithm = { + .smbus_xfer = smu_smbus_xfer, + .functionality = smu_smbus_func, +}; + +static int create_iface(struct device_node *np, struct device *dev) +{ + struct smu_iface* iface; + u32 *reg, busid; + int rc; + + reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) { + printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n"); + return -ENXIO; + } + busid = *reg; + + iface = kmalloc(sizeof(struct smu_iface), GFP_KERNEL); + if (iface == NULL) { + printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n"); + return -ENOMEM; + } + memset(iface, 0, sizeof(struct smu_iface)); + init_completion(&iface->complete); + iface->busid = busid; + + dev_set_drvdata(dev, iface); + + sprintf(iface->adapter.name, "smu-i2c-%02x", busid); + iface->adapter.algo = &smu_algorithm; + iface->adapter.algo_data = NULL; + iface->adapter.client_register = NULL; + iface->adapter.client_unregister = NULL; + i2c_set_adapdata(&iface->adapter, iface); + iface->adapter.dev.parent = dev; + + rc = i2c_add_adapter(&iface->adapter); + if (rc) { + printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration " + "failed\n", iface->adapter.name); + i2c_set_adapdata(&iface->adapter, NULL); + } + + if (probe) { + unsigned char addr; + printk("Probe: "); + for (addr = 0x00; addr <= 0x7f; addr++) { + if (i2c_smbus_xfer(&iface->adapter,addr, + 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) + printk("%02x ", addr); + } + printk("\n"); + } + + printk(KERN_INFO "SMU i2c bus %x registered\n", busid); + + return 0; +} + +static int dispose_iface(struct device *dev) +{ + struct smu_iface *iface = dev_get_drvdata(dev); + int rc; + + rc = i2c_del_adapter(&iface->adapter); + i2c_set_adapdata(&iface->adapter, NULL); + /* We aren't that prepared to deal with this... */ + if (rc) + printk("i2c-pmac-smu.c: Failed to remove bus %s !\n", + iface->adapter.name); + dev_set_drvdata(dev, NULL); + kfree(iface); + + return 0; +} + + +static int create_iface_of_platform(struct of_device* dev, + const struct of_device_id *match) +{ + return create_iface(dev->node, &dev->dev); +} + + +static int dispose_iface_of_platform(struct of_device* dev) +{ + return dispose_iface(&dev->dev); +} + + +static struct of_device_id i2c_smu_match[] = +{ + { + .compatible = "smu-i2c", + }, + {}, +}; +static struct of_platform_driver i2c_smu_of_platform_driver = +{ + .name = "i2c-smu", + .match_table = i2c_smu_match, + .probe = create_iface_of_platform, + .remove = dispose_iface_of_platform +}; + + +static int __init i2c_pmac_smu_init(void) +{ + of_register_driver(&i2c_smu_of_platform_driver); + return 0; +} + + +static void __exit i2c_pmac_smu_cleanup(void) +{ + of_unregister_driver(&i2c_smu_of_platform_driver); +} + +module_init(i2c_pmac_smu_init); +module_exit(i2c_pmac_smu_cleanup); diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index fb53573..a85ac18 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -8,21 +8,15 @@ */ /* - * For now, this driver includes: - * - RTC get & set - * - reboot & shutdown commands - * all synchronous with IRQ disabled (ugh) - * * TODO: - * rework in a way the PMU driver works, that is asynchronous - * with a queue of commands. I'll do that as soon as I have an - * SMU based machine at hand. Some more cleanup is needed too, - * like maybe fitting it into a platform device, etc... - * Also check what's up with cache coherency, and if we really - * can't do better than flushing the cache, maybe build a table - * of command len/reply len like the PMU driver to only flush - * what is actually necessary. - * --BenH. + * - maybe add timeout to commands ? + * - blocking version of time functions + * - polling version of i2c commands (including timer that works with + * interrutps off) + * - maybe avoid some data copies with i2c by directly using the smu cmd + * buffer and a lower level internal interface + * - understand SMU -> CPU events and implement reception of them via + * the userland interface */ #include @@ -36,6 +30,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -45,8 +44,13 @@ #include #include #include +#include +#include + +#define VERSION "0.6" +#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." -#define DEBUG_SMU 1 +#undef DEBUG_SMU #ifdef DEBUG_SMU #define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) @@ -57,20 +61,30 @@ /* * This is the command buffer passed to the SMU hardware */ +#define SMU_MAX_DATA 254 + struct smu_cmd_buf { u8 cmd; u8 length; - u8 data[0x0FFE]; + u8 data[SMU_MAX_DATA]; }; struct smu_device { spinlock_t lock; struct device_node *of_node; - int db_ack; /* doorbell ack GPIO */ - int db_req; /* doorbell req GPIO */ + struct of_device *of_dev; + int doorbell; /* doorbell gpio */ u32 __iomem *db_buf; /* doorbell buffer */ + int db_irq; + int msg; + int msg_irq; struct smu_cmd_buf *cmd_buf; /* command buffer virtual */ u32 cmd_buf_abs; /* command buffer absolute */ + struct list_head cmd_list; + struct smu_cmd *cmd_cur; /* pending command */ + struct list_head cmd_i2c_list; + struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ + struct timer_list i2c_timer; }; /* @@ -79,113 +93,243 @@ struct smu_device { */ static struct smu_device *smu; + /* - * SMU low level communication stuff + * SMU driver low level stuff */ -static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack) -{ - rmb(); - return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0; -} -static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf) +static void smu_start_cmd(void) { - return (~cmd_buf->cmd) & 0xff; -} + unsigned long faddr, fend; + struct smu_cmd *cmd; -static void smu_send_cmd(struct smu_device *dev) -{ - /* SMU command buf is currently cacheable, we need a physical - * address. This isn't exactly a DMA mapping here, I suspect + if (list_empty(&smu->cmd_list)) + return; + + /* Fetch first command in queue */ + cmd = list_entry(smu->cmd_list.next, struct smu_cmd, link); + smu->cmd_cur = cmd; + list_del(&cmd->link); + + DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, + cmd->data_len); + DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + + /* Fill the SMU command buffer */ + smu->cmd_buf->cmd = cmd->cmd; + smu->cmd_buf->length = cmd->data_len; + memcpy(smu->cmd_buf->data, cmd->data_buf, cmd->data_len); + + /* Flush command and data to RAM */ + faddr = (unsigned long)smu->cmd_buf; + fend = faddr + smu->cmd_buf->length + 2; + flush_inval_dcache_range(faddr, fend); + + /* This isn't exactly a DMA mapping here, I suspect * the SMU is actually communicating with us via i2c to the * northbridge or the CPU to access RAM. */ - writel(dev->cmd_buf_abs, dev->db_buf); + writel(smu->cmd_buf_abs, smu->db_buf); /* Ring the SMU doorbell */ - pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4); - pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4); + pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, smu->doorbell, 4); } -static int smu_cmd_done(struct smu_device *dev) + +static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs) { - unsigned long wait = 0; - int gpio; + unsigned long flags; + struct smu_cmd *cmd; + void (*done)(struct smu_cmd *cmd, void *misc) = NULL; + void *misc = NULL; + u8 gpio; + int rc = 0; - /* Check the SMU doorbell */ - do { - gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, - NULL, dev->db_ack); - if ((gpio & 7) == 7) - return 0; - udelay(100); - } while(++wait < 10000); + /* SMU completed the command, well, we hope, let's make sure + * of it + */ + spin_lock_irqsave(&smu->lock, flags); - printk(KERN_ERR "SMU timeout !\n"); - return -ENXIO; + gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); + if ((gpio & 7) != 7) + return IRQ_HANDLED; + + cmd = smu->cmd_cur; + smu->cmd_cur = NULL; + if (cmd == NULL) + goto bail; + + if (rc == 0) { + unsigned long faddr; + int reply_len; + u8 ack; + + /* CPU might have brought back the cache line, so we need + * to flush again before peeking at the SMU response. We + * flush the entire buffer for now as we haven't read the + * reply lenght (it's only 2 cache lines anyway) + */ + faddr = (unsigned long)smu->cmd_buf; + flush_inval_dcache_range(faddr, faddr + 256); + + /* Now check ack */ + ack = (~cmd->cmd) & 0xff; + if (ack != smu->cmd_buf->cmd) { + DPRINTK("SMU: incorrect ack, want %x got %x\n", + ack, smu->cmd_buf->cmd); + rc = -EIO; + } + reply_len = rc == 0 ? smu->cmd_buf->length : 0; + DPRINTK("SMU: reply len: %d\n", reply_len); + if (reply_len > cmd->reply_len) { + printk(KERN_WARNING "SMU: reply buffer too small," + "got %d bytes for a %d bytes buffer\n", + reply_len, cmd->reply_len); + reply_len = cmd->reply_len; + } + cmd->reply_len = reply_len; + if (cmd->reply_buf && reply_len) + memcpy(cmd->reply_buf, smu->cmd_buf->data, reply_len); + } + + /* Now complete the command. Write status last in order as we lost + * ownership of the command structure as soon as it's no longer -1 + */ + done = cmd->done; + misc = cmd->misc; + mb(); + cmd->status = rc; + bail: + /* Start next command if any */ + smu_start_cmd(); + spin_unlock_irqrestore(&smu->lock, flags); + + /* Call command completion handler if any */ + if (done) + done(cmd, misc); + + /* It's an edge interrupt, nothing to do */ + return IRQ_HANDLED; } -static int smu_do_cmd(struct smu_device *dev) + +static irqreturn_t smu_msg_intr(int irq, void *arg, struct pt_regs *regs) { - int rc; - u8 cmd_ack; + /* I don't quite know what to do with this one, we seem to never + * receive it, so I suspect we have to arm it someway in the SMU + * to start getting events that way. + */ + + printk(KERN_INFO "SMU: message interrupt !\n"); - DPRINTK("SMU do_cmd %02x len=%d %02x\n", - dev->cmd_buf->cmd, dev->cmd_buf->length, - dev->cmd_buf->data[0]); + /* It's an edge interrupt, nothing to do */ + return IRQ_HANDLED; +} - cmd_ack = smu_save_ack_cmd(dev->cmd_buf); - /* Clear cmd_buf cache lines */ - flush_inval_dcache_range((unsigned long)dev->cmd_buf, - ((unsigned long)dev->cmd_buf) + - sizeof(struct smu_cmd_buf)); - smu_send_cmd(dev); - rc = smu_cmd_done(dev); - if (rc == 0) - rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1; +/* + * Queued command management. + * + */ - DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n", - dev->cmd_buf->cmd, dev->cmd_buf->length, - dev->cmd_buf->data[0], rc, cmd_ack); +int smu_queue_cmd(struct smu_cmd *cmd) +{ + unsigned long flags; - return rc; + if (smu == NULL) + return -ENODEV; + if (cmd->data_len > SMU_MAX_DATA || + cmd->reply_len > SMU_MAX_DATA) + return -EINVAL; + + cmd->status = 1; + spin_lock_irqsave(&smu->lock, flags); + list_add_tail(&cmd->link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + spin_unlock_irqrestore(&smu->lock, flags); + + return 0; } +EXPORT_SYMBOL(smu_queue_cmd); -/* RTC low level commands */ -static inline int bcd2hex (int n) + +int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command, + unsigned int data_len, + void (*done)(struct smu_cmd *cmd, void *misc), + void *misc, ...) { - return (((n & 0xf0) >> 4) * 10) + (n & 0xf); + struct smu_cmd *cmd = &scmd->cmd; + va_list list; + int i; + + if (data_len > sizeof(scmd->buffer)) + return -EINVAL; + + memset(scmd, 0, sizeof(*scmd)); + cmd->cmd = command; + cmd->data_len = data_len; + cmd->data_buf = scmd->buffer; + cmd->reply_len = sizeof(scmd->buffer); + cmd->reply_buf = scmd->buffer; + cmd->done = done; + cmd->misc = misc; + + va_start(list, misc); + for (i = 0; i < data_len; ++i) + scmd->buffer[i] = (u8)va_arg(list, int); + va_end(list); + + return smu_queue_cmd(cmd); } +EXPORT_SYMBOL(smu_queue_simple); -static inline int hex2bcd (int n) + +void smu_poll(void) { - return ((n / 10) << 4) + (n % 10); + u8 gpio; + + if (smu == NULL) + return; + + gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); + if ((gpio & 7) == 7) + smu_db_intr(smu->db_irq, smu, NULL); } +EXPORT_SYMBOL(smu_poll); + -#if 0 -static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) +void smu_done_complete(struct smu_cmd *cmd, void *misc) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 8; - cmd_buf->data[0] = 0x00; - memset(cmd_buf->data + 1, 0, 7); + struct completion *comp = misc; + + complete(comp); } +EXPORT_SYMBOL(smu_done_complete); + -static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) +void smu_spinwait_cmd(struct smu_cmd *cmd) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x01; + while(cmd->status == 1) + smu_poll(); +} +EXPORT_SYMBOL(smu_spinwait_cmd); + + +/* RTC low level commands */ +static inline int bcd2hex (int n) +{ + return (((n & 0xf0) >> 4) * 10) + (n & 0xf); } -static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf) + +static inline int hex2bcd (int n) { - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x02; + return ((n / 10) << 4) + (n % 10); } -#endif + static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf, struct rtc_time *time) @@ -202,100 +346,96 @@ static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf, cmd_buf->data[7] = hex2bcd(time->tm_year - 100); } -static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf) -{ - cmd_buf->cmd = 0x8e; - cmd_buf->length = 1; - cmd_buf->data[0] = 0x81; -} -static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf, - struct rtc_time *time) +int smu_get_rtc_time(struct rtc_time *time, int spinwait) { - time->tm_sec = bcd2hex(cmd_buf->data[0]); - time->tm_min = bcd2hex(cmd_buf->data[1]); - time->tm_hour = bcd2hex(cmd_buf->data[2]); - time->tm_wday = bcd2hex(cmd_buf->data[3]); - time->tm_mday = bcd2hex(cmd_buf->data[4]); - time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1; - time->tm_year = bcd2hex(cmd_buf->data[6]) + 100; -} - -int smu_get_rtc_time(struct rtc_time *time) -{ - unsigned long flags; + struct smu_simple_cmd cmd; int rc; if (smu == NULL) return -ENODEV; memset(time, 0, sizeof(struct rtc_time)); - spin_lock_irqsave(&smu->lock, flags); - smu_fill_get_rtc_cmd(smu->cmd_buf); - rc = smu_do_cmd(smu); - if (rc == 0) - smu_parse_get_rtc_reply(smu->cmd_buf, time); - spin_unlock_irqrestore(&smu->lock, flags); + rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 1, NULL, NULL, + SMU_CMD_RTC_GET_DATETIME); + if (rc) + return rc; + smu_spinwait_simple(&cmd); - return rc; + time->tm_sec = bcd2hex(cmd.buffer[0]); + time->tm_min = bcd2hex(cmd.buffer[1]); + time->tm_hour = bcd2hex(cmd.buffer[2]); + time->tm_wday = bcd2hex(cmd.buffer[3]); + time->tm_mday = bcd2hex(cmd.buffer[4]); + time->tm_mon = bcd2hex(cmd.buffer[5]) - 1; + time->tm_year = bcd2hex(cmd.buffer[6]) + 100; + + return 0; } -int smu_set_rtc_time(struct rtc_time *time) + +int smu_set_rtc_time(struct rtc_time *time, int spinwait) { - unsigned long flags; + struct smu_simple_cmd cmd; int rc; if (smu == NULL) return -ENODEV; - spin_lock_irqsave(&smu->lock, flags); - smu_fill_set_rtc_cmd(smu->cmd_buf, time); - rc = smu_do_cmd(smu); - spin_unlock_irqrestore(&smu->lock, flags); + rc = smu_queue_simple(&cmd, SMU_CMD_RTC_COMMAND, 8, NULL, NULL, + SMU_CMD_RTC_SET_DATETIME, + hex2bcd(time->tm_sec), + hex2bcd(time->tm_min), + hex2bcd(time->tm_hour), + time->tm_wday, + hex2bcd(time->tm_mday), + hex2bcd(time->tm_mon) + 1, + hex2bcd(time->tm_year - 100)); + if (rc) + return rc; + smu_spinwait_simple(&cmd); - return rc; + return 0; } + void smu_shutdown(void) { - const unsigned char *command = "SHUTDOWN"; - unsigned long flags; + struct smu_simple_cmd cmd; if (smu == NULL) return; - spin_lock_irqsave(&smu->lock, flags); - smu->cmd_buf->cmd = 0xaa; - smu->cmd_buf->length = strlen(command); - strcpy(smu->cmd_buf->data, command); - smu_do_cmd(smu); + if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 9, NULL, NULL, + 'S', 'H', 'U', 'T', 'D', 'O', 'W', 'N', 0)) + return; + smu_spinwait_simple(&cmd); for (;;) ; - spin_unlock_irqrestore(&smu->lock, flags); } + void smu_restart(void) { - const unsigned char *command = "RESTART"; - unsigned long flags; + struct smu_simple_cmd cmd; if (smu == NULL) return; - spin_lock_irqsave(&smu->lock, flags); - smu->cmd_buf->cmd = 0xaa; - smu->cmd_buf->length = strlen(command); - strcpy(smu->cmd_buf->data, command); - smu_do_cmd(smu); + if (smu_queue_simple(&cmd, SMU_CMD_POWER_COMMAND, 8, NULL, NULL, + 'R', 'E', 'S', 'T', 'A', 'R', 'T', 0)) + return; + smu_spinwait_simple(&cmd); for (;;) ; - spin_unlock_irqrestore(&smu->lock, flags); } + int smu_present(void) { return smu != NULL; } +EXPORT_SYMBOL(smu_present); int smu_init (void) @@ -307,6 +447,8 @@ int smu_init (void) if (np == NULL) return -ENODEV; + printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); + if (smu_cmdbuf_abs == 0) { printk(KERN_ERR "SMU: Command buffer not allocated !\n"); return -EINVAL; @@ -318,7 +460,13 @@ int smu_init (void) memset(smu, 0, sizeof(*smu)); spin_lock_init(&smu->lock); + INIT_LIST_HEAD(&smu->cmd_list); + INIT_LIST_HEAD(&smu->cmd_i2c_list); smu->of_node = np; + smu->db_irq = NO_IRQ; + smu->msg_irq = NO_IRQ; + init_timer(&smu->i2c_timer); + /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a * 32 bits value safely */ @@ -331,8 +479,8 @@ int smu_init (void) goto fail; } data = (u32 *)get_property(np, "reg", NULL); - of_node_put(np); if (data == NULL) { + of_node_put(np); printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n"); goto fail; } @@ -341,8 +489,31 @@ int smu_init (void) * and ack. GPIOs are at 0x50, best would be to find that out * in the device-tree though. */ - smu->db_req = 0x50 + *data; - smu->db_ack = 0x50 + *data; + smu->doorbell = *data; + if (smu->doorbell < 0x50) + smu->doorbell += 0x50; + if (np->n_intrs > 0) + smu->db_irq = np->intrs[0].line; + + of_node_put(np); + + /* Now look for the smu-interrupt GPIO */ + do { + np = of_find_node_by_name(NULL, "smu-interrupt"); + if (np == NULL) + break; + data = (u32 *)get_property(np, "reg", NULL); + if (data == NULL) { + of_node_put(np); + break; + } + smu->msg = *data; + if (smu->msg < 0x50) + smu->msg += 0x50; + if (np->n_intrs > 0) + smu->msg_irq = np->intrs[0].line; + of_node_put(np); + } while(0); /* Doorbell buffer is currently hard-coded, I didn't find a proper * device-tree entry giving the address. Best would probably to use @@ -362,3 +533,584 @@ int smu_init (void) return -ENXIO; } + + +static int smu_late_init(void) +{ + if (!smu) + return 0; + + /* + * Try to request the interrupts + */ + + if (smu->db_irq != NO_IRQ) { + if (request_irq(smu->db_irq, smu_db_intr, + SA_SHIRQ, "SMU doorbell", smu) < 0) { + printk(KERN_WARNING "SMU: can't " + "request interrupt %d\n", + smu->db_irq); + smu->db_irq = NO_IRQ; + } + } + + if (smu->msg_irq != NO_IRQ) { + if (request_irq(smu->msg_irq, smu_msg_intr, + SA_SHIRQ, "SMU message", smu) < 0) { + printk(KERN_WARNING "SMU: can't " + "request interrupt %d\n", + smu->msg_irq); + smu->msg_irq = NO_IRQ; + } + } + + return 0; +} +arch_initcall(smu_late_init); + +/* + * sysfs visibility + */ + +static void smu_expose_childs(void *unused) +{ + struct device_node *np; + + for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) { + if (device_is_compatible(np, "smu-i2c")) { + char name[32]; + u32 *reg = (u32 *)get_property(np, "reg", NULL); + + if (reg == NULL) + continue; + sprintf(name, "smu-i2c-%02x", *reg); + of_platform_device_create(np, name, &smu->of_dev->dev); + } + } + +} + +static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); + +static int smu_platform_probe(struct of_device* dev, + const struct of_device_id *match) +{ + if (!smu) + return -ENODEV; + smu->of_dev = dev; + + /* + * Ok, we are matched, now expose all i2c busses. We have to defer + * that unfortunately or it would deadlock inside the device model + */ + schedule_work(&smu_expose_childs_work); + + return 0; +} + +static struct of_device_id smu_platform_match[] = +{ + { + .type = "smu", + }, + {}, +}; + +static struct of_platform_driver smu_of_platform_driver = +{ + .name = "smu", + .match_table = smu_platform_match, + .probe = smu_platform_probe, +}; + +static int __init smu_init_sysfs(void) +{ + int rc; + + /* + * Due to sysfs bogosity, a sysdev is not a real device, so + * we should in fact create both if we want sysdev semantics + * for power management. + * For now, we don't power manage machines with an SMU chip, + * I'm a bit too far from figuring out how that works with those + * new chipsets, but that will come back and bite us + */ + rc = of_register_driver(&smu_of_platform_driver); + return 0; +} + +device_initcall(smu_init_sysfs); + +struct of_device *smu_get_ofdev(void) +{ + if (!smu) + return NULL; + return smu->of_dev; +} + +EXPORT_SYMBOL_GPL(smu_get_ofdev); + +/* + * i2c interface + */ + +static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail) +{ + void (*done)(struct smu_i2c_cmd *cmd, void *misc) = cmd->done; + void *misc = cmd->misc; + unsigned long flags; + + /* Check for read case */ + if (!fail && cmd->read) { + if (cmd->pdata[0] < 1) + fail = 1; + else + memcpy(cmd->info.data, &cmd->pdata[1], + cmd->info.datalen); + } + + DPRINTK("SMU: completing, success: %d\n", !fail); + + /* Update status and mark no pending i2c command with lock + * held so nobody comes in while we dequeue an eventual + * pending next i2c command + */ + spin_lock_irqsave(&smu->lock, flags); + smu->cmd_i2c_cur = NULL; + wmb(); + cmd->status = fail ? -EIO : 0; + + /* Is there another i2c command waiting ? */ + if (!list_empty(&smu->cmd_i2c_list)) { + struct smu_i2c_cmd *newcmd; + + /* Fetch it, new current, remove from list */ + newcmd = list_entry(smu->cmd_i2c_list.next, + struct smu_i2c_cmd, link); + smu->cmd_i2c_cur = newcmd; + list_del(&cmd->link); + + /* Queue with low level smu */ + list_add_tail(&cmd->scmd.link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + } + spin_unlock_irqrestore(&smu->lock, flags); + + /* Call command completion handler if any */ + if (done) + done(cmd, misc); + +} + + +static void smu_i2c_retry(unsigned long data) +{ + struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data; + + DPRINTK("SMU: i2c failure, requeuing...\n"); + + /* requeue command simply by resetting reply_len */ + cmd->pdata[0] = 0xff; + cmd->scmd.reply_len = 0x10; + smu_queue_cmd(&cmd->scmd); +} + + +static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc) +{ + struct smu_i2c_cmd *cmd = misc; + int fail = 0; + + DPRINTK("SMU: i2c compl. stage=%d status=%x pdata[0]=%x rlen: %x\n", + cmd->stage, scmd->status, cmd->pdata[0], scmd->reply_len); + + /* Check for possible status */ + if (scmd->status < 0) + fail = 1; + else if (cmd->read) { + if (cmd->stage == 0) + fail = cmd->pdata[0] != 0; + else + fail = cmd->pdata[0] >= 0x80; + } else { + fail = cmd->pdata[0] != 0; + } + + /* Handle failures by requeuing command, after 5ms interval + */ + if (fail && --cmd->retries > 0) { + DPRINTK("SMU: i2c failure, starting timer...\n"); + smu->i2c_timer.function = smu_i2c_retry; + smu->i2c_timer.data = (unsigned long)cmd; + smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5); + add_timer(&smu->i2c_timer); + return; + } + + /* If failure or stage 1, command is complete */ + if (fail || cmd->stage != 0) { + smu_i2c_complete_command(cmd, fail); + return; + } + + DPRINTK("SMU: going to stage 1\n"); + + /* Ok, initial command complete, now poll status */ + scmd->reply_buf = cmd->pdata; + scmd->reply_len = 0x10; + scmd->data_buf = cmd->pdata; + scmd->data_len = 1; + cmd->pdata[0] = 0; + cmd->stage = 1; + cmd->retries = 20; + smu_queue_cmd(scmd); +} + + +int smu_queue_i2c(struct smu_i2c_cmd *cmd) +{ + unsigned long flags; + + if (smu == NULL) + return -ENODEV; + + /* Fill most fields of scmd */ + cmd->scmd.cmd = SMU_CMD_I2C_COMMAND; + cmd->scmd.done = smu_i2c_low_completion; + cmd->scmd.misc = cmd; + cmd->scmd.reply_buf = cmd->pdata; + cmd->scmd.reply_len = 0x10; + cmd->scmd.data_buf = (u8 *)(char *)&cmd->info; + cmd->scmd.status = 1; + cmd->stage = 0; + cmd->pdata[0] = 0xff; + cmd->retries = 20; + cmd->status = 1; + + /* Check transfer type, sanitize some "info" fields + * based on transfer type and do more checking + */ + cmd->info.caddr = cmd->info.devaddr; + cmd->read = cmd->info.devaddr & 0x01; + switch(cmd->info.type) { + case SMU_I2C_TRANSFER_SIMPLE: + memset(&cmd->info.sublen, 0, 4); + break; + case SMU_I2C_TRANSFER_COMBINED: + cmd->info.devaddr &= 0xfe; + case SMU_I2C_TRANSFER_STDSUB: + if (cmd->info.sublen > 3) + return -EINVAL; + break; + default: + return -EINVAL; + } + + /* Finish setting up command based on transfer direction + */ + if (cmd->read) { + if (cmd->info.datalen > SMU_I2C_READ_MAX) + return -EINVAL; + memset(cmd->info.data, 0xff, cmd->info.datalen); + cmd->scmd.data_len = 9; + } else { + if (cmd->info.datalen > SMU_I2C_WRITE_MAX) + return -EINVAL; + cmd->scmd.data_len = 9 + cmd->info.datalen; + } + + DPRINTK("SMU: i2c enqueuing command\n"); + DPRINTK("SMU: %s, len=%d bus=%x addr=%x sub0=%x type=%x\n", + cmd->read ? "read" : "write", cmd->info.datalen, + cmd->info.bus, cmd->info.caddr, + cmd->info.subaddr[0], cmd->info.type); + + + /* Enqueue command in i2c list, and if empty, enqueue also in + * main command list + */ + spin_lock_irqsave(&smu->lock, flags); + if (smu->cmd_i2c_cur == NULL) { + smu->cmd_i2c_cur = cmd; + list_add_tail(&cmd->scmd.link, &smu->cmd_list); + if (smu->cmd_cur == NULL) + smu_start_cmd(); + } else + list_add_tail(&cmd->link, &smu->cmd_i2c_list); + spin_unlock_irqrestore(&smu->lock, flags); + + return 0; +} + + + +/* + * Userland driver interface + */ + + +static LIST_HEAD(smu_clist); +static DEFINE_SPINLOCK(smu_clist_lock); + +enum smu_file_mode { + smu_file_commands, + smu_file_events, + smu_file_closing +}; + +struct smu_private +{ + struct list_head list; + enum smu_file_mode mode; + int busy; + struct smu_cmd cmd; + spinlock_t lock; + wait_queue_head_t wait; + u8 buffer[SMU_MAX_DATA]; +}; + + +static int smu_open(struct inode *inode, struct file *file) +{ + struct smu_private *pp; + unsigned long flags; + + pp = kmalloc(sizeof(struct smu_private), GFP_KERNEL); + if (pp == 0) + return -ENOMEM; + memset(pp, 0, sizeof(struct smu_private)); + spin_lock_init(&pp->lock); + pp->mode = smu_file_commands; + init_waitqueue_head(&pp->wait); + + spin_lock_irqsave(&smu_clist_lock, flags); + list_add(&pp->list, &smu_clist); + spin_unlock_irqrestore(&smu_clist_lock, flags); + file->private_data = pp; + + return 0; +} + + +static void smu_user_cmd_done(struct smu_cmd *cmd, void *misc) +{ + struct smu_private *pp = misc; + + wake_up_all(&pp->wait); +} + + +static ssize_t smu_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct smu_private *pp = file->private_data; + unsigned long flags; + struct smu_user_cmd_hdr hdr; + int rc = 0; + + if (pp->busy) + return -EBUSY; + else if (copy_from_user(&hdr, buf, sizeof(hdr))) + return -EFAULT; + else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { + pp->mode = smu_file_events; + return 0; + } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) + return -EINVAL; + else if (pp->mode != smu_file_commands) + return -EBADFD; + else if (hdr.data_len > SMU_MAX_DATA) + return -EINVAL; + + spin_lock_irqsave(&pp->lock, flags); + if (pp->busy) { + spin_unlock_irqrestore(&pp->lock, flags); + return -EBUSY; + } + pp->busy = 1; + pp->cmd.status = 1; + spin_unlock_irqrestore(&pp->lock, flags); + + if (copy_from_user(pp->buffer, buf + sizeof(hdr), hdr.data_len)) { + pp->busy = 0; + return -EFAULT; + } + + pp->cmd.cmd = hdr.cmd; + pp->cmd.data_len = hdr.data_len; + pp->cmd.reply_len = SMU_MAX_DATA; + pp->cmd.data_buf = pp->buffer; + pp->cmd.reply_buf = pp->buffer; + pp->cmd.done = smu_user_cmd_done; + pp->cmd.misc = pp; + rc = smu_queue_cmd(&pp->cmd); + if (rc < 0) + return rc; + return count; +} + + +static ssize_t smu_read_command(struct file *file, struct smu_private *pp, + char __user *buf, size_t count) +{ + DECLARE_WAITQUEUE(wait, current); + struct smu_user_reply_hdr hdr; + unsigned long flags; + int size, rc = 0; + + if (!pp->busy) + return 0; + if (count < sizeof(struct smu_user_reply_hdr)) + return -EOVERFLOW; + spin_lock_irqsave(&pp->lock, flags); + if (pp->cmd.status == 1) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + add_wait_queue(&pp->wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + rc = 0; + if (pp->cmd.status != 1) + break; + rc = -ERESTARTSYS; + if (signal_pending(current)) + break; + spin_unlock_irqrestore(&pp->lock, flags); + schedule(); + spin_lock_irqsave(&pp->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&pp->wait, &wait); + } + spin_unlock_irqrestore(&pp->lock, flags); + if (rc) + return rc; + if (pp->cmd.status != 0) + pp->cmd.reply_len = 0; + size = sizeof(hdr) + pp->cmd.reply_len; + if (count < size) + size = count; + rc = size; + hdr.status = pp->cmd.status; + hdr.reply_len = pp->cmd.reply_len; + if (copy_to_user(buf, &hdr, sizeof(hdr))) + return -EFAULT; + size -= sizeof(hdr); + if (size && copy_to_user(buf + sizeof(hdr), pp->buffer, size)) + return -EFAULT; + pp->busy = 0; + + return rc; +} + + +static ssize_t smu_read_events(struct file *file, struct smu_private *pp, + char __user *buf, size_t count) +{ + /* Not implemented */ + msleep_interruptible(1000); + return 0; +} + + +static ssize_t smu_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct smu_private *pp = file->private_data; + + if (pp->mode == smu_file_commands) + return smu_read_command(file, pp, buf, count); + if (pp->mode == smu_file_events) + return smu_read_events(file, pp, buf, count); + + return -EBADFD; +} + +static unsigned int smu_fpoll(struct file *file, poll_table *wait) +{ + struct smu_private *pp = file->private_data; + unsigned int mask = 0; + unsigned long flags; + + if (pp == 0) + return 0; + + if (pp->mode == smu_file_commands) { + poll_wait(file, &pp->wait, wait); + + spin_lock_irqsave(&pp->lock, flags); + if (pp->busy && pp->cmd.status != 1) + mask |= POLLIN; + spin_unlock_irqrestore(&pp->lock, flags); + } if (pp->mode == smu_file_events) { + /* Not yet implemented */ + } + return mask; +} + +static int smu_release(struct inode *inode, struct file *file) +{ + struct smu_private *pp = file->private_data; + unsigned long flags; + unsigned int busy; + + if (pp == 0) + return 0; + + file->private_data = NULL; + + /* Mark file as closing to avoid races with new request */ + spin_lock_irqsave(&pp->lock, flags); + pp->mode = smu_file_closing; + busy = pp->busy; + + /* Wait for any pending request to complete */ + if (busy && pp->cmd.status == 1) { + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&pp->wait, &wait); + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (pp->cmd.status != 1) + break; + spin_lock_irqsave(&pp->lock, flags); + schedule(); + spin_unlock_irqrestore(&pp->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&pp->wait, &wait); + } + spin_unlock_irqrestore(&pp->lock, flags); + + spin_lock_irqsave(&smu_clist_lock, flags); + list_del(&pp->list); + spin_unlock_irqrestore(&smu_clist_lock, flags); + kfree(pp); + + return 0; +} + + +static struct file_operations smu_device_fops __pmacdata = { + .llseek = no_llseek, + .read = smu_read, + .write = smu_write, + .poll = smu_fpoll, + .open = smu_open, + .release = smu_release, +}; + +static struct miscdevice pmu_device __pmacdata = { + MISC_DYNAMIC_MINOR, "smu", &smu_device_fops +}; + +static int smu_device_init(void) +{ + if (!smu) + return -ENODEV; + if (misc_register(&pmu_device) < 0) + printk(KERN_ERR "via-pmu: cannot register misc device.\n"); + return 0; +} +device_initcall(smu_device_init); diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c9ca111..f386966 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -599,7 +599,7 @@ thermostat_init(void) sensor_location[2] = "?"; } - of_dev = of_platform_device_create(np, "temperatures"); + of_dev = of_platform_device_create(np, "temperatures", NULL); if (of_dev == NULL) { printk(KERN_ERR "Can't register temperatures device !\n"); diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 703e3197..cc507ce 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -2051,7 +2051,7 @@ static int __init therm_pm72_init(void) return -ENODEV; } } - of_dev = of_platform_device_create(np, "temperature"); + of_dev = of_platform_device_create(np, "temperature", NULL); if (of_dev == NULL) { printk(KERN_ERR "Can't register FCU platform device !\n"); return -ENODEV; diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index cbb72eb..6aaa1df 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -504,7 +504,7 @@ g4fan_init( void ) } if( !(np=of_find_node_by_name(NULL, "fan")) ) return -ENODEV; - x.of_dev = of_platform_device_create( np, "temperature" ); + x.of_dev = of_platform_device_create(np, "temperature", NULL); of_node_put( np ); if( !x.of_dev ) { diff --git a/include/asm-ppc/macio.h b/include/asm-ppc/macio.h index a481b77..b553dd4 100644 --- a/include/asm-ppc/macio.h +++ b/include/asm-ppc/macio.h @@ -1,7 +1,6 @@ #ifndef __MACIO_ASIC_H__ #define __MACIO_ASIC_H__ -#include #include extern struct bus_type macio_bus_type; diff --git a/include/asm-ppc/of_device.h b/include/asm-ppc/of_device.h index 4b264cf..575bce4 100644 --- a/include/asm-ppc/of_device.h +++ b/include/asm-ppc/of_device.h @@ -2,6 +2,7 @@ #define __OF_DEVICE_H__ #include +#include #include /* @@ -55,7 +56,9 @@ extern int of_register_driver(struct of_platform_driver *drv); extern void of_unregister_driver(struct of_platform_driver *drv); extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent); extern void of_release_dev(struct device *dev); #endif /* __OF_DEVICE_H__ */ diff --git a/include/asm-ppc64/smu.h b/include/asm-ppc64/smu.h index 10b4397..dee8eef 100644 --- a/include/asm-ppc64/smu.h +++ b/include/asm-ppc64/smu.h @@ -1,22 +1,379 @@ +#ifndef _SMU_H +#define _SMU_H + /* * Definitions for talking to the SMU chip in newer G5 PowerMacs */ #include +#include + +/* + * Known SMU commands + * + * Most of what is below comes from looking at the Open Firmware driver, + * though this is still incomplete and could use better documentation here + * or there... + */ + + +/* + * Partition info commands + * + * I do not know what those are for at this point + */ +#define SMU_CMD_PARTITION_COMMAND 0x3e + + +/* + * Fan control + * + * This is a "mux" for fan control commands, first byte is the + * "sub" command. + */ +#define SMU_CMD_FAN_COMMAND 0x4a + + +/* + * Battery access + * + * Same command number as the PMU, could it be same syntax ? + */ +#define SMU_CMD_BATTERY_COMMAND 0x6f +#define SMU_CMD_GET_BATTERY_INFO 0x00 + +/* + * Real time clock control + * + * This is a "mux", first data byte contains the "sub" command. + * The "RTC" part of the SMU controls the date, time, powerup + * timer, but also a PRAM + * + * Dates are in BCD format on 7 bytes: + * [sec] [min] [hour] [weekday] [month day] [month] [year] + * with month being 1 based and year minus 100 + */ +#define SMU_CMD_RTC_COMMAND 0x8e +#define SMU_CMD_RTC_SET_PWRUP_TIMER 0x00 /* i: 7 bytes date */ +#define SMU_CMD_RTC_GET_PWRUP_TIMER 0x01 /* o: 7 bytes date */ +#define SMU_CMD_RTC_STOP_PWRUP_TIMER 0x02 +#define SMU_CMD_RTC_SET_PRAM_BYTE_ACC 0x20 /* i: 1 byte (address?) */ +#define SMU_CMD_RTC_SET_PRAM_AUTOINC 0x21 /* i: 1 byte (data?) */ +#define SMU_CMD_RTC_SET_PRAM_LO_BYTES 0x22 /* i: 10 bytes */ +#define SMU_CMD_RTC_SET_PRAM_HI_BYTES 0x23 /* i: 10 bytes */ +#define SMU_CMD_RTC_GET_PRAM_BYTE 0x28 /* i: 1 bytes (address?) */ +#define SMU_CMD_RTC_GET_PRAM_LO_BYTES 0x29 /* o: 10 bytes */ +#define SMU_CMD_RTC_GET_PRAM_HI_BYTES 0x2a /* o: 10 bytes */ +#define SMU_CMD_RTC_SET_DATETIME 0x80 /* i: 7 bytes date */ +#define SMU_CMD_RTC_GET_DATETIME 0x81 /* o: 7 bytes date */ + + /* + * i2c commands + * + * To issue an i2c command, first is to send a parameter block to the + * the SMU. This is a command of type 0x9a with 9 bytes of header + * eventually followed by data for a write: + * + * 0: bus number (from device-tree usually, SMU has lots of busses !) + * 1: transfer type/format (see below) + * 2: device address. For combined and combined4 type transfers, this + * is the "write" version of the address (bit 0x01 cleared) + * 3: subaddress length (0..3) + * 4: subaddress byte 0 (or only byte for subaddress length 1) + * 5: subaddress byte 1 + * 6: subaddress byte 2 + * 7: combined address (device address for combined mode data phase) + * 8: data length + * + * The transfer types are the same good old Apple ones it seems, + * that is: + * - 0x00: Simple transfer + * - 0x01: Subaddress transfer (addr write + data tx, no restart) + * - 0x02: Combined transfer (addr write + restart + data tx) + * + * This is then followed by actual data for a write. + * + * At this point, the OF driver seems to have a limitation on transfer + * sizes of 0xd bytes on reads and 0x5 bytes on writes. I do not know + * wether this is just an OF limit due to some temporary buffer size + * or if this is an SMU imposed limit. This driver has the same limitation + * for now as I use a 0x10 bytes temporary buffer as well + * + * Once that is completed, a response is expected from the SMU. This is + * obtained via a command of type 0x9a with a length of 1 byte containing + * 0 as the data byte. OF also fills the rest of the data buffer with 0xff's + * though I can't tell yet if this is actually necessary. Once this command + * is complete, at this point, all I can tell is what OF does. OF tests + * byte 0 of the reply: + * - on read, 0xfe or 0xfc : bus is busy, wait (see below) or nak ? + * - on read, 0x00 or 0x01 : reply is in buffer (after the byte 0) + * - on write, < 0 -> failure (immediate exit) + * - else, OF just exists (without error, weird) + * + * So on read, there is this wait-for-busy thing when getting a 0xfc or + * 0xfe result. OF does a loop of up to 64 retries, waiting 20ms and + * doing the above again until either the retries expire or the result + * is no longer 0xfe or 0xfc + * + * The Darwin I2C driver is less subtle though. On any non-success status + * from the response command, it waits 5ms and tries again up to 20 times, + * it doesn't differenciate between fatal errors or "busy" status. + * + * This driver provides an asynchronous paramblock based i2c command + * interface to be used either directly by low level code or by a higher + * level driver interfacing to the linux i2c layer. The current + * implementation of this relies on working timers & timer interrupts + * though, so be careful of calling context for now. This may be "fixed" + * in the future by adding a polling facility. + */ +#define SMU_CMD_I2C_COMMAND 0x9a + /* transfer types */ +#define SMU_I2C_TRANSFER_SIMPLE 0x00 +#define SMU_I2C_TRANSFER_STDSUB 0x01 +#define SMU_I2C_TRANSFER_COMBINED 0x02 + +/* + * Power supply control + * + * The "sub" command is an ASCII string in the data, the + * data lenght is that of the string. + * + * The VSLEW command can be used to get or set the voltage slewing. + * - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of + * reply at data offset 6, 7 and 8. + * - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is + * used to set the voltage slewing point. The SMU replies with "DONE" + * I yet have to figure out their exact meaning of those 3 bytes in + * both cases. + * + */ +#define SMU_CMD_POWER_COMMAND 0xaa +#define SMU_CMD_POWER_RESTART "RESTART" +#define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" +#define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" + +/* Misc commands + * + * This command seem to be a grab bag of various things + */ +#define SMU_CMD_MISC_df_COMMAND 0xdf +#define SMU_CMD_MISC_df_SET_DISPLAY_LIT 0x02 /* i: 1 byte */ +#define SMU_CMD_MISC_df_NMI_OPTION 0x04 + +/* + * Version info commands + * + * I haven't quite tried to figure out how these work + */ +#define SMU_CMD_VERSION_COMMAND 0xea + + +/* + * Misc commands + * + * This command seem to be a grab bag of various things + */ +#define SMU_CMD_MISC_ee_COMMAND 0xee +#define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 +#define SMU_CMD_MISC_ee_LEDS_CTRL 0x04 /* i: 00 (00,01) [00] */ +#define SMU_CMD_MISC_ee_GET_DATA 0x05 /* i: 00 , o: ?? */ + + + +/* + * - Kernel side interface - + */ + +#ifdef __KERNEL__ + +/* + * Asynchronous SMU commands + * + * Fill up this structure and submit it via smu_queue_command(), + * and get notified by the optional done() callback, or because + * status becomes != 1 + */ + +struct smu_cmd; + +struct smu_cmd +{ + /* public */ + u8 cmd; /* command */ + int data_len; /* data len */ + int reply_len; /* reply len */ + void *data_buf; /* data buffer */ + void *reply_buf; /* reply buffer */ + int status; /* command status */ + void (*done)(struct smu_cmd *cmd, void *misc); + void *misc; + + /* private */ + struct list_head link; +}; + +/* + * Queues an SMU command, all fields have to be initialized + */ +extern int smu_queue_cmd(struct smu_cmd *cmd); + +/* + * Simple command wrapper. This structure embeds a small buffer + * to ease sending simple SMU commands from the stack + */ +struct smu_simple_cmd +{ + struct smu_cmd cmd; + u8 buffer[16]; +}; + +/* + * Queues a simple command. All fields will be initialized by that + * function + */ +extern int smu_queue_simple(struct smu_simple_cmd *scmd, u8 command, + unsigned int data_len, + void (*done)(struct smu_cmd *cmd, void *misc), + void *misc, + ...); + +/* + * Completion helper. Pass it to smu_queue_simple or as 'done' + * member to smu_queue_cmd, it will call complete() on the struct + * completion passed in the "misc" argument + */ +extern void smu_done_complete(struct smu_cmd *cmd, void *misc); /* - * Basic routines for use by architecture. To be extended as - * we understand more of the chip + * Synchronous helpers. Will spin-wait for completion of a command + */ +extern void smu_spinwait_cmd(struct smu_cmd *cmd); + +static inline void smu_spinwait_simple(struct smu_simple_cmd *scmd) +{ + smu_spinwait_cmd(&scmd->cmd); +} + +/* + * Poll routine to call if blocked with irqs off + */ +extern void smu_poll(void); + + +/* + * Init routine, presence check.... */ extern int smu_init(void); extern int smu_present(void); +struct of_device; +extern struct of_device *smu_get_ofdev(void); + + +/* + * Common command wrappers + */ extern void smu_shutdown(void); extern void smu_restart(void); -extern int smu_get_rtc_time(struct rtc_time *time); -extern int smu_set_rtc_time(struct rtc_time *time); +struct rtc_time; +extern int smu_get_rtc_time(struct rtc_time *time, int spinwait); +extern int smu_set_rtc_time(struct rtc_time *time, int spinwait); /* * SMU command buffer absolute address, exported by pmac_setup, * this is allocated very early during boot. */ extern unsigned long smu_cmdbuf_abs; + + +/* + * Kenrel asynchronous i2c interface + */ + +/* SMU i2c header, exactly matches i2c header on wire */ +struct smu_i2c_param +{ + u8 bus; /* SMU bus ID (from device tree) */ + u8 type; /* i2c transfer type */ + u8 devaddr; /* device address (includes direction) */ + u8 sublen; /* subaddress length */ + u8 subaddr[3]; /* subaddress */ + u8 caddr; /* combined address, filled by SMU driver */ + u8 datalen; /* length of transfer */ + u8 data[7]; /* data */ +}; + +#define SMU_I2C_READ_MAX 0x0d +#define SMU_I2C_WRITE_MAX 0x05 + +struct smu_i2c_cmd +{ + /* public */ + struct smu_i2c_param info; + void (*done)(struct smu_i2c_cmd *cmd, void *misc); + void *misc; + int status; /* 1 = pending, 0 = ok, <0 = fail */ + + /* private */ + struct smu_cmd scmd; + int read; + int stage; + int retries; + u8 pdata[0x10]; + struct list_head link; +}; + +/* + * Call this to queue an i2c command to the SMU. You must fill info, + * including info.data for a write, done and misc. + * For now, no polling interface is provided so you have to use completion + * callback. + */ +extern int smu_queue_i2c(struct smu_i2c_cmd *cmd); + + +#endif /* __KERNEL__ */ + +/* + * - Userland interface - + */ + +/* + * A given instance of the device can be configured for 2 different + * things at the moment: + * + * - sending SMU commands (default at open() time) + * - receiving SMU events (not yet implemented) + * + * Commands are written with write() of a command block. They can be + * "driver" commands (for example to switch to event reception mode) + * or real SMU commands. They are made of a header followed by command + * data if any. + * + * For SMU commands (not for driver commands), you can then read() back + * a reply. The reader will be blocked or not depending on how the device + * file is opened. poll() isn't implemented yet. The reply will consist + * of a header as well, followed by the reply data if any. You should + * always provide a buffer large enough for the maximum reply data, I + * recommand one page. + * + * It is illegal to send SMU commands through a file descriptor configured + * for events reception + * + */ +struct smu_user_cmd_hdr +{ + __u32 cmdtype; +#define SMU_CMDTYPE_SMU 0 /* SMU command */ +#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ + + __u8 cmd; /* SMU command byte */ + __u32 data_len; /* Lenght of data following */ +}; + +struct smu_user_reply_hdr +{ + __u32 status; /* Command status */ + __u32 reply_len; /* Lenght of data follwing */ +}; + +#endif /* _SMU_H */ -- cgit v0.10.2 From e3fc4cc17ac4dbadab0ba0d5c8233d3b18170d4a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 22 Sep 2005 21:44:07 -0700 Subject: [PATCH] corrections to top-level README Corrections to the recent top-level README changes. Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/README b/README index 2b5844d..d1edcc7 100644 --- a/README +++ b/README @@ -151,7 +151,7 @@ CONFIGURING the kernel: your existing ./.config file. "make silentoldconfig" Like above, but avoids cluttering the screen - with question already answered. + with questions already answered. NOTES on "make config": - having unnecessary drivers will make the kernel bigger, and can @@ -199,9 +199,9 @@ COMPILING the kernel: are installing a new kernel with the same version number as your working kernel, make a backup of your modules directory before you do a "make modules_install". - In alternative, before compiling, edit your Makefile and change the - "EXTRAVERSION" line - its content is appended to the regular kernel - version. + Alternatively, before compiling, use the kernel config option + "LOCALVERSION" to append a unique suffix to the regular kernel version. + LOCALVERSION can be set in the "General Setup" menu. - In order to boot your new kernel, you'll need to copy the kernel image (e.g. .../linux/arch/i386/boot/bzImage after compilation) -- cgit v0.10.2 From 98b4f5929ce5e616d0d0e13c71baf50083ab7397 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu, 22 Sep 2005 21:44:08 -0700 Subject: [PATCH] atiixp_modem printk fixes Correctly identify atiixp_modem in its error messages. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Vojtech Pavlik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 8a59598..c1a239a 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -405,7 +405,7 @@ static int snd_atiixp_acquire_codec(atiixp_t *chip) while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) { if (! timeout--) { - snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n"); + snd_printk(KERN_WARNING "atiixp-modem: codec acquire timeout\n"); return -EBUSY; } udelay(1); @@ -436,7 +436,7 @@ static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec } while (--timeout); /* time out may happen during reset */ if (reg < 0x7c) - snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg); + snd_printk(KERN_WARNING "atiixp-modem: codec read timeout (reg %x)\n", reg); return 0xffff; } @@ -498,7 +498,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip) do_delay(); atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); if (--timeout) { - snd_printk(KERN_ERR "atiixp: codec reset timeout\n"); + snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n"); break; } } @@ -552,7 +552,7 @@ static int snd_atiixp_codec_detect(atiixp_t *chip) atiixp_write(chip, IER, 0); /* disable irqs */ if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) { - snd_printk(KERN_ERR "atiixp: no codec detected!\n"); + snd_printk(KERN_ERR "atiixp-modem: no codec detected!\n"); return -ENXIO; } return 0; @@ -635,7 +635,7 @@ static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma) { if (! dma->substream || ! dma->running) return; - snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type); + snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); } @@ -1081,14 +1081,14 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock) ac97.scaps = AC97_SCAP_SKIP_AUDIO; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { chip->ac97[i] = NULL; /* to be sure */ - snd_printdd("atiixp: codec %d not available for modem\n", i); + snd_printdd("atiixp-modem: codec %d not available for modem\n", i); continue; } codec_count++; } if (! codec_count) { - snd_printk(KERN_ERR "atiixp: no codec available\n"); + snd_printk(KERN_ERR "atiixp-modem: no codec available\n"); return -ENODEV; } @@ -1159,7 +1159,7 @@ static void __devinit snd_atiixp_proc_init(atiixp_t *chip) { snd_info_entry_t *entry; - if (! snd_card_proc_new(chip->card, "atiixp", &entry)) + if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); } -- cgit v0.10.2 From 0cdc82ee1ae36c1ae4631fc3a782faeb0b90df38 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 22 Sep 2005 21:44:09 -0700 Subject: [PATCH] mesh scsi: fix error handling The PowerMac mesh SCSI driver had some missing error handling which would trigger warnings due to lack of handling of return value from scsi_add_host. This fixes it. Signed-off-by: Benjamin Herrenschmidt Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index a4857db..b235556 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1959,22 +1959,35 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) /* Set it up */ mesh_init(ms); - /* XXX FIXME: error should be fatal */ - if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms)) + /* Request interrupt */ + if (request_irq(ms->meshintr, do_mesh_interrupt, 0, "MESH", ms)) { printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr); + goto out_shutdown; + } - /* XXX FIXME: handle failure */ - scsi_add_host(mesh_host, &mdev->ofdev.dev); + /* Add scsi host & scan */ + if (scsi_add_host(mesh_host, &mdev->ofdev.dev)) + goto out_release_irq; scsi_scan_host(mesh_host); return 0; -out_unmap: + out_release_irq: + free_irq(ms->meshintr, ms); + out_shutdown: + /* shutdown & reset bus in case of error or macos can be confused + * at reboot if the bus was set to synchronous mode already + */ + mesh_shutdown(mdev); + set_mesh_power(ms, 0); + pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size, + ms->dma_cmd_space, ms->dma_cmd_bus); + out_unmap: iounmap(ms->dma); iounmap(ms->mesh); -out_free: + out_free: scsi_host_put(mesh_host); -out_release: + out_release: macio_release_resources(mdev); return -ENODEV; @@ -2001,7 +2014,7 @@ static int mesh_remove(struct macio_dev *mdev) /* Free DMA commands memory */ pci_free_consistent(macio_get_pci_dev(mdev), ms->dma_cmd_size, - ms->dma_cmd_space, ms->dma_cmd_bus); + ms->dma_cmd_space, ms->dma_cmd_bus); /* Release memory resources */ macio_release_resources(mdev); -- cgit v0.10.2 From eafb42707b21beb42bba4eae7b742f837ee9d2e0 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 22 Sep 2005 21:44:10 -0700 Subject: [PATCH] __kmalloc: Generate BUG if size requested is too large. I had an issue on ia64 where I got a bug in kernel/workqueue because kzalloc returned a NULL pointer due to the task structure getting too big for the slab allocator. Usually these cases are caught by the kmalloc macro in include/linux/slab.h. Compilation will fail if a too big value is passed to kmalloc. However, kzalloc uses __kmalloc which has no check for that. This patch makes __kmalloc bug if a too large entity is requested. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index c9adfce..ad113c4 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2907,8 +2907,7 @@ void *__kmalloc(size_t size, unsigned int __nocast flags) * functions. */ cachep = __find_general_cachep(size, flags); - if (unlikely(cachep == NULL)) - return NULL; + BUG_ON(!cachep); /* Allocation size too large for kmalloc */ return __cache_alloc(cachep, flags); } EXPORT_SYMBOL(__kmalloc); -- cgit v0.10.2 From 8686bcd0a5f5e3f599ed9f1028ec9e449e7b87e3 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Thu, 22 Sep 2005 21:44:11 -0700 Subject: [PATCH] swsusp: fix comments Fix comments in swsusp. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/power.h b/kernel/power/power.h index cd6a349..9c9167d 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -1,7 +1,7 @@ #include #include -/* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but +/* With SUSPEND_CONSOLE defined suspend looks *really* cool, but we probably do not take enough locks for switching consoles, etc, so bad things might happen. */ diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 353f37f..1cc9ff2 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -363,7 +363,7 @@ static void lock_swapdevices(void) } /** - * write_swap_page - Write one page to a fresh swap location. + * write_page - Write one page to a fresh swap location. * @addr: Address we're writing. * @loc: Place to store the entry we used. * @@ -863,6 +863,9 @@ static int alloc_image_pages(void) return 0; } +/* Free pages we allocated for suspend. Suspend pages are alocated + * before atomic copy, so we need to free them after resume. + */ void swsusp_free(void) { BUG_ON(PageNosave(virt_to_page(pagedir_save))); @@ -1213,8 +1216,9 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) free_pagedir(pblist); free_eaten_memory(); pblist = NULL; - } - else + /* Is this even worth handling? It should never ever happen, and we + have just lost user's state, anyway... */ + } else printk("swsusp: Relocated %d pages\n", rel); return pblist; -- cgit v0.10.2 From 3a02d6c051cf3c214aab38e4330b4bcec5f6e3f8 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:12 -0700 Subject: [PATCH] uml: don't remove umid files in conflict case Only remove the UML pidfile and management socket if we created them. Currently in case two UMLs are started with the same umid, the second will remove the first's ones. Probably we should also panic() at that point, not sure however. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 186c288..251d277 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -31,6 +31,8 @@ static char *uml_dir = UML_DIR; /* Changed by set_umid */ static int umid_is_random = 1; static int umid_inited = 0; +/* Have we created the files? Should we remove them? */ +static int umid_owned = 0; static int make_umid(int (*printer)(const char *fmt, ...)); @@ -82,20 +84,21 @@ int __init umid_file_name(char *name, char *buf, int len) extern int tracing_pid; -static int __init create_pid_file(void) +static void __init create_pid_file(void) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")]; int fd, n; - if(umid_file_name("pid", file, sizeof(file))) return 0; + if(umid_file_name("pid", file, sizeof(file))) + return; fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 0644); if(fd < 0){ printf("Open of machine pid file \"%s\" failed: %s\n", file, strerror(-fd)); - return 0; + return; } sprintf(pid, "%d\n", os_getpid()); @@ -103,7 +106,6 @@ static int __init create_pid_file(void) if(n != strlen(pid)) printf("Write of pid file failed - err = %d\n", -n); os_close_file(fd); - return 0; } static int actually_do_remove(char *dir) @@ -147,7 +149,8 @@ static int actually_do_remove(char *dir) void remove_umid_dir(void) { char dir[strlen(uml_dir) + UMID_LEN + 1]; - if(!umid_inited) return; + if (!umid_owned) + return; sprintf(dir, "%s%s", uml_dir, umid); actually_do_remove(dir); @@ -155,11 +158,12 @@ void remove_umid_dir(void) char *get_umid(int only_if_set) { - if(only_if_set && umid_is_random) return(NULL); - return(umid); + if(only_if_set && umid_is_random) + return NULL; + return umid; } -int not_dead_yet(char *dir) +static int not_dead_yet(char *dir) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; @@ -193,7 +197,8 @@ int not_dead_yet(char *dir) (p == CHOOSE_MODE(tracing_pid, os_getpid()))) dead = 1; } - if(!dead) return(1); + if(!dead) + return(1); return(actually_do_remove(dir)); } @@ -286,6 +291,7 @@ static int __init make_umid(int (*printer)(const char *fmt, ...)) if(errno == EEXIST){ if(not_dead_yet(tmp)){ (*printer)("umid '%s' is in use\n", umid); + umid_owned = 0; return(-1); } err = mkdir(tmp, 0777); @@ -296,7 +302,8 @@ static int __init make_umid(int (*printer)(const char *fmt, ...)) return(-1); } - return(0); + umid_owned = 1; + return 0; } __uml_setup("uml_dir=", set_uml_dir, @@ -309,7 +316,8 @@ static int __init make_umid_setup(void) /* one function with the ordering we need ... */ make_uml_dir(); make_umid(printf); - return create_pid_file(); + create_pid_file(); + return 0; } __uml_postsetup(make_umid_setup); -- cgit v0.10.2 From a8bfb94c58238666df0d6856861d18f0f52fc752 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:14 -0700 Subject: [PATCH] strlcat: use for uml umid.c Simplify the code by using strlcat() instead of strncat() and manual appending. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/user.h b/arch/um/include/user.h index 57ee9e2..0f865ef 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -14,7 +14,9 @@ extern void *um_kmalloc_atomic(int size); extern void kfree(void *ptr); extern int in_aton(char *str); extern int open_gdb_chan(void); -extern int strlcpy(char *, const char *, int); +/* These use size_t, however unsigned long is correct on both i386 and x86_64. */ +extern unsigned long strlcpy(char *, const char *, unsigned long); +extern unsigned long strlcat(char *, const char *, unsigned long); extern void *um_vmalloc(int size); extern void vfree(void *ptr); diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 251d277..0b21d59 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -237,16 +237,13 @@ static int __init make_uml_dir(void) strlcpy(dir, home, sizeof(dir)); uml_dir++; } + strlcat(dir, uml_dir, sizeof(dir)); len = strlen(dir); - strncat(dir, uml_dir, sizeof(dir) - len); - len = strlen(dir); - if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){ - dir[len] = '/'; - dir[len + 1] = '\0'; - } + if (len > 0 && dir[len - 1] != '/') + strlcat(dir, "/", sizeof(dir)); uml_dir = malloc(strlen(dir) + 1); - if(uml_dir == NULL){ + if (uml_dir == NULL) { printf("make_uml_dir : malloc failed, errno = %d\n", errno); exit(1); } -- cgit v0.10.2 From 69e1e688f5698287b45fbff22a01de91b20804cd Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:15 -0700 Subject: [PATCH] uml: don't redundantly mark pte as newpage in pte_modify pte_modify marks a page as needing flush, which is redundant because the resulting PTE is still set with set_pte, which already handles that. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h index ed06170..616d02b 100644 --- a/include/asm-um/pgtable.h +++ b/include/asm-um/pgtable.h @@ -346,7 +346,6 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_set_val(pte, (pte_val(pte) & _PAGE_CHG_MASK), newprot); - if(pte_present(pte)) pte = pte_mknewpage(pte_mknewprot(pte)); return pte; } -- cgit v0.10.2 From 546fe1cbf91d4d62e3849517c31a2327c992e5c5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:16 -0700 Subject: [PATCH] uml: fix hang in TT mode on fault The current code doesn't handle well general protection faults on the host - it thinks that cr2 is always the address of a page fault. While actually, on general protection faults, that address is not accessible, so we'd better assume we couldn't satisfy the fault. Currently instead we think we've fixed it, so we go back, retry the instruction and fault again endlessly. This leads to the kernel hanging when doing copy_from_user(dest, -1, ...) in TT mode, since reading *(-1) causes a GFP, and we don't support kernel preemption. Thanks to Luo Xin for testing UML with LTP and reporting the failures he got. Cc: Luo Xin Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 87cc6fd..90690b9 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -18,6 +18,7 @@ #include "asm/a.out.h" #include "asm/current.h" #include "asm/irq.h" +#include "sysdep/sigcontext.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" @@ -125,7 +126,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) } else if(current->mm == NULL) panic("Segfault with no mm"); - err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + + if (SEGV_IS_FIXABLE(&fi)) + err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + else { + err = -EFAULT; + /* A thread accessed NULL, we get a fault, but CR2 is invalid. + * This code is used in __do_copy_from_user() of TT mode. */ + address = 0; + } catcher = current->thread.fault_catcher; if(!err) diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index f014755..8c220f0 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c @@ -22,8 +22,15 @@ int __do_copy_from_user(void *to, const void *from, int n, __do_copy, &faulted); TASK_REGS(get_current())->tt = save; - if(!faulted) return(0); - else return(n - (fault - (unsigned long) from)); + if(!faulted) + return 0; + else if (fault) + return n - (fault - (unsigned long) from); + else + /* In case of a general protection fault, we don't have the + * fault address, so NULL is used instead. Pretend we didn't + * copy anything. */ + return n; } static void __do_strncpy(void *dst, const void *src, int count) -- cgit v0.10.2 From dc36abf34e13aabbe06cdd060c434b3cdd80e7da Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:18 -0700 Subject: [PATCH] uml: fix condition in tlb flush Avoid setting w = 0 twice. Spotted this (trivial) thing which is needed for another patch. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 0a562c3..f5b0636 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -193,12 +193,12 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, r = pte_read(*npte); w = pte_write(*npte); x = pte_exec(*npte); - if(!pte_dirty(*npte)) - w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } + if (!pte_young(*npte)) { + r = 0; + w = 0; + } else if (!pte_dirty(*npte)) { + w = 0; + } if(force || pte_newpage(*npte)){ if(pte_present(*npte)) ret = add_mmap(addr, -- cgit v0.10.2 From 12ebcd73e40e09f0dfddf89e465cc0541e0ff8b1 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:19 -0700 Subject: [PATCH] uml: run mconsole "sysrq" in process context Things are breaking horribly with sysrq called in interrupt context. I want to try to fix it, but probably this is simpler. To tell the truth, sysrq is normally run in interrupt context, so there shouldn't be any problem. There's also a warning from the fault handler because it's run in atomic context (I have a patch for that, only I deferred it). This is why I'm doing this. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 310c1f8..04383f9 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -23,7 +23,7 @@ static struct mconsole_command commands[] = { { "reboot", mconsole_reboot, MCONSOLE_PROC }, { "config", mconsole_config, MCONSOLE_PROC }, { "remove", mconsole_remove, MCONSOLE_PROC }, - { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, + { "sysrq", mconsole_sysrq, MCONSOLE_PROC }, { "help", mconsole_help, MCONSOLE_INTR }, { "cad", mconsole_cad, MCONSOLE_INTR }, { "stop", mconsole_stop, MCONSOLE_PROC }, -- cgit v0.10.2 From fea03cb40a15e3c6647c0927300202e062e6792a Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:20 -0700 Subject: [PATCH] uml: avoid fixing faults while atomic Following i386, we should maybe refuse trying to fault in pages when we're doing atomic operations, because to handle the fault we could need to take already taken spinlocks. Also, if we're doing an atomic operation (in the sense of in_atomic()) we're surely in kernel mode and we're surely going to handle adequately the failed fault, so it's safe to behave this way. Currently, on UML SMP is rarely used, and we don't support PREEMPT, so this is unlikely to create problems right now, but it might in the future. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 90690b9..d297429 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -40,6 +40,12 @@ int handle_page_fault(unsigned long address, unsigned long ip, int err = -EFAULT; *code_out = SEGV_MAPERR; + + /* If the fault was during atomic operation, don't take the fault, just + * fail. */ + if (in_atomic()) + goto out_nosemaphore; + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if(!vma) @@ -90,6 +96,7 @@ survive: flush_tlb_page(vma, address); out: up_read(&mm->mmap_sem); +out_nosemaphore: return(err); /* -- cgit v0.10.2 From 46db4a42dd1190a311c2fb45106dfd0842c65a94 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:20 -0700 Subject: [PATCH] uml: Fix GFP_ flags usage GFP_ATOMIC | GFP_KERNEL is meaningless and won't work. Actually it never worked, even in 2.4. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 39cf568..ea65db6 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -82,7 +82,8 @@ unsigned long alloc_stack(int order, int atomic) unsigned long page; int flags = GFP_KERNEL; - if(atomic) flags |= GFP_ATOMIC; + if (atomic) + flags = GFP_ATOMIC; page = __get_free_pages(flags, order); if(page == 0) return(0); -- cgit v0.10.2 From 79ae2cb856ed6a8c48f455d52d5ed5960c671e67 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:21 -0700 Subject: [PATCH] uml: use GFP_ATOMIC for allocations under spinlocks. setup_initial_poll is only called with sigio_lock() held, so use appropriate allocation. Also, parse_chan() can also be called when holding a spinlock (see line_open() -> parse_chan_pair()). I have sporadic problems (spinlock taken twice, with spinlock debugging on UP) which could be caused by a sequence like "take spinlock, alloc and go to sleep, take again the spinlock in the other thread". Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 14a12d6..244e54a 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -465,7 +465,7 @@ static struct chan *parse_chan(char *str, int pri, int device, data = (*ops->init)(str, device, opts); if(data == NULL) return(NULL); - chan = kmalloc(sizeof(*chan), GFP_KERNEL); + chan = kmalloc(sizeof(*chan), GFP_ATOMIC); if(chan == NULL) return(NULL); *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), .primary = 1, diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index e892189..a527511 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -340,7 +340,7 @@ static int setup_initial_poll(int fd) { struct pollfd *p; - p = um_kmalloc(sizeof(struct pollfd)); + p = um_kmalloc_atomic(sizeof(struct pollfd)); if(p == NULL){ printk("setup_initial_poll : failed to allocate poll\n"); return(-1); -- cgit v0.10.2 From fac97ae0b1a206e2952baf1f9eb46305d673adc6 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:22 -0700 Subject: [PATCH] uml: replace printk with "stack-friendly" printf - to report console failure User get *a lot* confused when consoles don't work but we don't report anything. And, as reported in the comment, using printk to report "your console doesn't work" isn't likely to go that far. Fix the problem on the base of this: stack consumption by host printf(). Use kernel sprintf() and os_write_file, using a wild guess that one page will be enough for the message, to preallocate the buffer with kmalloc(). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Cc: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 244e54a..16e7dc8 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -19,18 +19,44 @@ #include "line.h" #include "os.h" -#ifdef CONFIG_NOCONFIG_CHAN +/* XXX: could well be moved to somewhere else, if needed. */ +static int my_printf(const char * fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static int my_printf(const char * fmt, ...) +{ + /* Yes, can be called on atomic context.*/ + char *buf = kmalloc(4096, GFP_ATOMIC); + va_list args; + int r; + + if (!buf) { + /* We print directly fmt. + * Yes, yes, yes, feel free to complain. */ + r = strlen(fmt); + } else { + va_start(args, fmt); + r = vsprintf(buf, fmt, args); + va_end(args); + fmt = buf; + } -/* The printk's here are wrong because we are complaining that there is no - * output device, but printk is printing to that output device. The user will - * never see the error. printf would be better, except it can't run on a - * kernel stack because it will overflow it. - * Use printk for now since that will avoid crashing. - */ + if (r) + r = os_write_file(1, fmt, r); + return r; + +} + +#ifdef CONFIG_NOCONFIG_CHAN +/* Despite its name, there's no added trailing newline. */ +static int my_puts(const char * buf) +{ + return os_write_file(1, buf, strlen(buf)); +} static void *not_configged_init(char *str, int device, struct chan_opts *opts) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(NULL); } @@ -38,27 +64,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) static int not_configged_open(int input, int output, int primary, void *data, char **dev_out) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(-ENODEV); } static void not_configged_close(int fd, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); } static int not_configged_read(int fd, char *c_out, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(-EIO); } static int not_configged_write(int fd, const char *buf, int len, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(-EIO); } @@ -66,7 +92,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) static int not_configged_console_write(int fd, const char *buf, int len, void *data) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(-EIO); } @@ -74,14 +100,14 @@ static int not_configged_console_write(int fd, const char *buf, int len, static int not_configged_window_size(int fd, void *data, unsigned short *rows, unsigned short *cols) { - printk(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); return(-ENODEV); } static void not_configged_free(void *data) { - printf(KERN_ERR "Using a channel type which is configured out of " + my_puts("Using a channel type which is configured out of " "UML\n"); } @@ -457,7 +483,7 @@ static struct chan *parse_chan(char *str, int pri, int device, } } if(ops == NULL){ - printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", + my_printf("parse_chan couldn't parse \"%s\"\n", str); return(NULL); } -- cgit v0.10.2 From 288a60cf4d7cc35f84f46cd8ffd0b34f9d8e7346 Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Thu, 22 Sep 2005 21:44:23 -0700 Subject: [PATCH] xtensa: remove io_remap_page_range and minor clean-ups Remove io_remap_page_range() from all of Linux 2.6.x (as requested and suggested by Randy Dunlap) and minor clean-ups. Signed-off-by: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 09887c9..de19501 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -402,8 +402,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); - ret = io_remap_page_range(vma, vma->vm_start, vma->vm_pgoff<vm_end - vma->vm_start, vma->vm_page_prot); + ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start,vma->vm_page_prot); return ret; } diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index cf13627..03674da 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -39,7 +39,7 @@ _F(int, pcibios_fixup, (void), { return 0; }); _F(int, get_rtc_time, (time_t* t), { return 0; }); _F(int, set_rtc_time, (time_t t), { return 0; }); -#if CONFIG_XTENSA_CALIBRATE_CCOUNT +#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT _F(void, calibrate_ccount, (void), { printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n"); diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index c83bb0d..08ef6d8 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -457,7 +457,7 @@ int dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) { /* see asm/coprocessor.h for this magic number 16 */ -#if TOTAL_CPEXTRA_SIZE > 16 +#if XTENSA_CP_EXTRA_SIZE > 16 do_save_fpregs (r, regs, task); /* For now, bit 16 means some extra state may be present: */ diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 1f5bf5d..513ed8d 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -304,7 +304,7 @@ void __init setup_arch(char **cmdline_p) # endif #endif -#if CONFIG_PCI +#ifdef CONFIG_PCI platform_pcibios_init(); #endif } diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index dc42ced..e252b61 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -182,7 +182,7 @@ restore_cpextra (struct _cpstate *buf) struct task_struct *tsk = current; release_all_cp(tsk); - return __copy_from_user(tsk->thread.cpextra, buf, TOTAL_CPEXTRA_SIZE); + return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE); #endif return 0; } diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 1ac7d5c..8e423d1 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -68,7 +68,7 @@ void __init time_init(void) * speed for the CALIBRATE. */ -#if CONFIG_XTENSA_CALIBRATE_CCOUNT +#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); platform_calibrate_ccount(); printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 56aace8..5a91d6c 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -239,7 +239,7 @@ void __init mem_init(void) high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); highmemsize = 0; -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM #error HIGHGMEM not implemented in init.c #endif diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h index 24f86f0..12b5732 100644 --- a/include/asm-xtensa/atomic.h +++ b/include/asm-xtensa/atomic.h @@ -22,7 +22,7 @@ typedef struct { volatile int counter; } atomic_t; #include #include -#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) +#define ATOMIC_INIT(i) { (i) } /* * This Xtensa implementation assumes that the right mechanism diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h index d395ef2..e76ee88 100644 --- a/include/asm-xtensa/bitops.h +++ b/include/asm-xtensa/bitops.h @@ -174,7 +174,7 @@ static __inline__ int test_bit(int nr, const volatile void *addr) return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31)); } -#if XCHAL_HAVE_NSAU +#if XCHAL_HAVE_NSA static __inline__ int __cntlz (unsigned long x) { diff --git a/include/asm-xtensa/hardirq.h b/include/asm-xtensa/hardirq.h index e07c76c..aa9c1ad 100644 --- a/include/asm-xtensa/hardirq.h +++ b/include/asm-xtensa/hardirq.h @@ -23,6 +23,7 @@ typedef struct { unsigned int __nmi_count; /* arch dependent */ } ____cacheline_aligned irq_cpustat_t; +void ack_bad_irq(unsigned int irq); #include /* Standard mappings for irq_cpustat_t above */ #endif /* _XTENSA_HARDIRQ_H */ diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h index db740b8..09e89ab 100644 --- a/include/asm-xtensa/semaphore.h +++ b/include/asm-xtensa/semaphore.h @@ -20,28 +20,19 @@ struct semaphore { atomic_t count; int sleepers; wait_queue_head_t wait; -#if WAITQUEUE_DEBUG - long __magic; -#endif }; -#if WAITQUEUE_DEBUG -# define __SEM_DEBUG_INIT(name) \ - , (int)&(name).__magic -#else -# define __SEM_DEBUG_INIT(name) -#endif - -#define __SEMAPHORE_INITIALIZER(name,count) \ - { ATOMIC_INIT(count), \ - 0, \ - __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ - __SEM_DEBUG_INIT(name) } +#define __SEMAPHORE_INITIALIZER(name,n) \ +{ \ + .count = ATOMIC_INIT(n), \ + .sleepers = 0, \ + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ +} -#define __MUTEX_INITIALIZER(name) \ +#define __MUTEX_INITIALIZER(name) \ __SEMAPHORE_INITIALIZER(name, 1) -#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ +#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) @@ -49,17 +40,8 @@ struct semaphore { static inline void sema_init (struct semaphore *sem, int val) { -/* - * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); - * - * i'd rather use the more flexible initialization above, but sadly - * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well. - */ atomic_set(&sem->count, val); init_waitqueue_head(&sem->wait); -#if WAITQUEUE_DEBUG - sem->__magic = (int)&sem->__magic; -#endif } static inline void init_MUTEX (struct semaphore *sem) @@ -81,9 +63,7 @@ extern spinlock_t semaphore_wake_lock; static inline void down(struct semaphore * sem) { -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif + might_sleep(); if (atomic_sub_return(1, &sem->count) < 0) __down(sem); @@ -92,9 +72,8 @@ static inline void down(struct semaphore * sem) static inline int down_interruptible(struct semaphore * sem) { int ret = 0; -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif + + might_sleep(); if (atomic_sub_return(1, &sem->count) < 0) ret = __down_interruptible(sem); @@ -104,9 +83,6 @@ static inline int down_interruptible(struct semaphore * sem) static inline int down_trylock(struct semaphore * sem) { int ret = 0; -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif if (atomic_sub_return(1, &sem->count) < 0) ret = __down_trylock(sem); @@ -119,9 +95,6 @@ static inline int down_trylock(struct semaphore * sem) */ static inline void up(struct semaphore * sem) { -#if WAITQUEUE_DEBUG - CHECK_MAGIC(sem->__magic); -#endif if (atomic_add_return(1, &sem->count) <= 0) __up(sem); } diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h index f093932..9284867 100644 --- a/include/asm-xtensa/system.h +++ b/include/asm-xtensa/system.h @@ -189,20 +189,6 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val) #define tas(ptr) (xchg((ptr),1)) -#if ( __XCC__ == 1 ) - -/* xt-xcc processes __inline__ differently than xt-gcc and decides to - * insert an out-of-line copy of function __xchg. This presents the - * unresolved symbol at link time of __xchg_called_with_bad_pointer, - * even though such a function would never be called at run-time. - * xt-gcc always inlines __xchg, and optimizes away the undefined - * bad_pointer function. - */ - -#define xchg(ptr,x) xchg_u32(ptr,x) - -#else /* assume xt-gcc */ - #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) /* @@ -224,8 +210,6 @@ __xchg(unsigned long x, volatile void * ptr, int size) return x; } -#endif - extern void set_except_vector(int n, void *addr); static inline void spill_registers(void) -- cgit v0.10.2 From f65d9bea8692d7343e4636763f291408f025834f Mon Sep 17 00:00:00 2001 From: Clemens Buchacher Date: Thu, 22 Sep 2005 21:44:24 -0700 Subject: [PATCH] oss: don't concatenate __FUNCTION__ with strings It's deprecated. Use "%s", __FUNCTION__ instead. Signed-off-by: Clemens Buchacher Signed-off-by: Maximilian Attems Signed-off-by: Domen Puncer Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c index 4491733..2c2ae2e 100644 --- a/sound/oss/au1000.c +++ b/sound/oss/au1000.c @@ -1295,7 +1295,7 @@ static int au1000_mmap(struct file *file, struct vm_area_struct *vma) unsigned long size; int ret = 0; - dbg(__FUNCTION__); + dbg("%s", __FUNCTION__); lock_kernel(); down(&s->sem); diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c index 58f879f..26e5944 100644 --- a/sound/oss/ite8172.c +++ b/sound/oss/ite8172.c @@ -1859,7 +1859,7 @@ static int it8172_release(struct inode *inode, struct file *file) struct it8172_state *s = (struct it8172_state *)file->private_data; #ifdef IT8172_VERBOSE_DEBUG - dbg(__FUNCTION__); + dbg("%s", __FUNCTION__); #endif lock_kernel(); if (file->f_mode & FMODE_WRITE) -- cgit v0.10.2 From 8bdac5d1ed892da54b6b2069e50a47b3aa39460f Mon Sep 17 00:00:00 2001 From: Glauber de Oliveira Costa Date: Thu, 22 Sep 2005 21:44:26 -0700 Subject: [PATCH] ext3: EXT3_DEBUG build fixes Fix some warnings and a build error when EXT3_DEBUG is enabled. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index e463dca..0213db4 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -1410,7 +1410,7 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) unsigned long desc_count; struct ext3_group_desc *gdp; int i; - unsigned long ngroups; + unsigned long ngroups = EXT3_SB(sb)->s_groups_count; #ifdef EXT3FS_DEBUG struct ext3_super_block *es; unsigned long bitmap_count, x; @@ -1421,7 +1421,8 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) desc_count = 0; bitmap_count = 0; gdp = NULL; - for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { + + for (i = 0; i < ngroups; i++) { gdp = ext3_get_group_desc(sb, i, NULL); if (!gdp) continue; @@ -1443,7 +1444,6 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) return bitmap_count; #else desc_count = 0; - ngroups = EXT3_SB(sb)->s_groups_count; smp_rmb(); for (i = 0; i < ngroups; i++) { gdp = ext3_get_group_desc(sb, i, NULL); diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 2c9f812..57f7910 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -242,7 +242,7 @@ static int setup_new_group_blocks(struct super_block *sb, i < sbi->s_itb_per_group; i++, bit++, block++) { struct buffer_head *it; - ext3_debug("clear inode block %#04x (+%ld)\n", block, bit); + ext3_debug("clear inode block %#04lx (+%d)\n", block, bit); if (IS_ERR(it = bclean(handle, sb, block))) { err = PTR_ERR(it); goto exit_bh; @@ -643,8 +643,8 @@ static void update_backups(struct super_block *sb, break; bh = sb_getblk(sb, group * bpg + blk_off); - ext3_debug(sb, __FUNCTION__, "update metadata backup %#04lx\n", - bh->b_blocknr); + ext3_debug("update metadata backup %#04lx\n", + (unsigned long)bh->b_blocknr); if ((err = ext3_journal_get_write_access(handle, bh))) break; lock_buffer(bh); -- cgit v0.10.2 From f7b3a4359b25311fb5894c8809478a2df6bed480 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Thu, 22 Sep 2005 21:44:27 -0700 Subject: [PATCH] Fix bd_claim() error code. Problem: In some circumstances, bd_claim() is returning the wrong error code. If we try to swapon an unused block device that isn't swap formatted, we get -EINVAL. But if that same block device is already mounted, we instead get -EBUSY, even though it still isn't a valid swap device. This issue came up on the busybox list trying to get the error message from "swapon -a" right. If a swap device is already enabled, we get -EBUSY, and we shouldn't report this as an error. But we can't distinguish the two -EBUSY conditions, which are very different errors. In the code, bd_claim() returns either 0 or -EBUSY, but in this case busy means "somebody other than sys_swapon has already claimed this", and _that_ means this block device can't be a valid swap device. So return -EINVAL there. Signed-off-by: Rob Landley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/swapfile.c b/mm/swapfile.c index 0184f51..1dcaeda 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1381,6 +1381,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) error = bd_claim(bdev, sys_swapon); if (error < 0) { bdev = NULL; + error = -EINVAL; goto bad_swap; } p->old_block_size = block_size(bdev); -- cgit v0.10.2 From 10d2c46f9408d404bffef89d5052953a3b1d9288 Mon Sep 17 00:00:00 2001 From: Nick Wilson Date: Thu, 22 Sep 2005 21:44:28 -0700 Subject: [PATCH] NFS: fix client oops when debugging is on nfs_readpage_release() causes an oops while accessing a file with NFS debugging turned on (echo 32767 > /proc/sys/sunrpc/nfs_debug) and a kernel built with CONFIG_DEBUG_SLAB. This patch moves the debugging statement above nfs_release_request() to avoid accessing freed memory. Signed-off-by: Nick Wilson Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6ceb1d4..9758ebd 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -184,14 +184,13 @@ static void nfs_readpage_release(struct nfs_page *req) { unlock_page(req->wb_page); - nfs_clear_request(req); - nfs_release_request(req); - dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", req->wb_context->dentry->d_inode->i_sb->s_id, (long long)NFS_FILEID(req->wb_context->dentry->d_inode), req->wb_bytes, (long long)req_offset(req)); + nfs_clear_request(req); + nfs_release_request(req); } /* -- cgit v0.10.2 From e484585ec3ee66cd07a627d3a9e2364640a3807f Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 22 Sep 2005 21:44:29 -0700 Subject: [PATCH] Add dm-snapshot tutorial in Documentation I've recently discovered the real functionality of device-mapper snapshots, and since they are not well known, I've decided to write some docs for them. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt new file mode 100644 index 0000000..dca274f --- /dev/null +++ b/Documentation/device-mapper/snapshot.txt @@ -0,0 +1,73 @@ +Device-mapper snapshot support +============================== + +Device-mapper allows you, without massive data copying: + +*) To create snapshots of any block device i.e. mountable, saved states of +the block device which are also writable without interfering with the +original content; +*) To create device "forks", i.e. multiple different versions of the +same data stream. + + +In both cases, dm copies only the chunks of data that get changed and +uses a separate copy-on-write (COW) block device for storage. + + +There are two dm targets available: snapshot and snapshot-origin. + +*) snapshot-origin + +which will normally have one or more snapshots based on it. +You must create the snapshot-origin device before you can create snapshots. +Reads will be mapped directly to the backing device. For each write, the +original data will be saved in the of each snapshot to keep +its visible content unchanged, at least until the fills up. + + +*) snapshot + +A snapshot is created of the block device. Changed chunks of + sectors will be stored on the . Writes will +only go to the . Reads will come from the or +from for unchanged data. will often be +smaller than the origin and if it fills up the snapshot will become +useless and be disabled, returning errors. So it is important to monitor +the amount of free space and expand the before it fills up. + + is P (Persistent) or N (Not persistent - will not survive +after reboot). + + +How this is used by LVM2 +======================== +When you create the first LVM2 snapshot of a volume, four dm devices are used: + +1) a device containing the original mapping table of the source volume; +2) a device used as the ; +3) a "snapshot" device, combining #1 and #2, which is the visible snapshot + volume; +4) the "original" volume (which uses the device number used by the original + source volume), whose table is replaced by a "snapshot-origin" mapping + from device #1. + +A fixed naming scheme is used, so with the following commands: + +lvcreate -L 1G -n base volumeGroup +lvcreate -L 100M --snapshot -n snap volumeGroup/base + +we'll have this situation (with volumes in above order): + +# dmsetup table|grep volumeGroup + +volumeGroup-base-real: 0 2097152 linear 8:19 384 +volumeGroup-snap-cow: 0 204800 linear 8:19 2097536 +volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16 +volumeGroup-base: 0 2097152 snapshot-origin 254:11 + +# ls -lL /dev/mapper/volumeGroup-* +brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real +brw------- 1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow +brw------- 1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap +brw------- 1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base + -- cgit v0.10.2 From 83ca28befc43e93849e79c564cda10e39d983e75 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 22 Sep 2005 23:32:56 -0700 Subject: [TCP]: Adjust Reno SACK estimate in tcp_fragment Since the introduction of TSO pcount a year ago, it has been possible for tcp_fragment() to cause packets_out to decrease. Prior to that, tcp_retrans_try_collapse() was the only way for that to happen on the retransmission path. When this happens with Reno, it is possible for sasked_out to become invalid because it is only an estimate and not tied to any particular packet on the retransmission queue. Therefore we need to adjust sacked_out as well as left_out in the Reno case. The following patch does exactly that. This bug is pretty difficult to trigger in practice though since you need a SACKless peer with a retransmission that occurs just as the cached MTU value expires. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5dd6dd7..d6e3d26 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -509,7 +509,16 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss tp->lost_out -= diff; tp->left_out -= diff; } + if (diff > 0) { + /* Adjust Reno SACK estimate. */ + if (!tp->rx_opt.sack_ok) { + tp->sacked_out -= diff; + if ((int)tp->sacked_out < 0) + tp->sacked_out = 0; + tcp_sync_left_out(tp); + } + tp->fackets_out -= diff; if ((int)tp->fackets_out < 0) tp->fackets_out = 0; -- cgit v0.10.2 From 2a7bc3c94cbca32d3d6e03e7d5a71662f591d28a Mon Sep 17 00:00:00 2001 From: Vlad Drukker Date: Thu, 22 Sep 2005 23:35:34 -0700 Subject: [BRIDGE]: TSO fix in br_dev_queue_push_xmit Signed-off-by: Vlad Drukker Acked-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 069253f..2d24fb4 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -31,7 +31,8 @@ static inline int should_deliver(const struct net_bridge_port *p, int br_dev_queue_push_xmit(struct sk_buff *skb) { - if (skb->len > skb->dev->mtu) + /* drop mtu oversized packets except tso */ + if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER -- cgit v0.10.2 From 0ae5d253adcc467b1c52b512bbca9419eb438409 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 22 Sep 2005 23:44:58 -0700 Subject: [NETFILTER] fix DEBUG statement in PPTP helper As noted by Alexey Dobriyan, the DEBUGP statement prints the wrong callID. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 79db5b7..1175879 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -485,7 +485,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, if (info->pns_call_id != ntohs(*pcid)) { DEBUGP("%s for unknown CallID %u\n", - pptp_msg_name[msg], ntohs(*cid)); + pptp_msg_name[msg], ntohs(*pcid)); break; } -- cgit v0.10.2 From 67497205b12e3cb408259cc09b50c3a9d12cd935 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 22 Sep 2005 23:45:24 -0700 Subject: [NETFILTER] Fix sparse endian warnings in pptp helper Signed-off-by: Alexey Dobriyan Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h index 389e385..50a761d 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h @@ -60,8 +60,8 @@ struct ip_ct_pptp_expect { struct pptp_pkt_hdr { __u16 packetLength; - __u16 packetType; - __u32 magicCookie; + __be16 packetType; + __be32 magicCookie; }; /* PptpControlMessageType values */ @@ -93,7 +93,7 @@ struct pptp_pkt_hdr { #define PPTP_REMOVE_DEVICE_ERROR 6 struct PptpControlHeader { - __u16 messageType; + __be16 messageType; __u16 reserved; }; @@ -106,13 +106,13 @@ struct PptpControlHeader { #define PPTP_BEARER_CAP_DIGITAL 0x2 struct PptpStartSessionRequest { - __u16 protocolVersion; + __be16 protocolVersion; __u8 reserved1; __u8 reserved2; - __u32 framingCapability; - __u32 bearerCapability; - __u16 maxChannels; - __u16 firmwareRevision; + __be32 framingCapability; + __be32 bearerCapability; + __be16 maxChannels; + __be16 firmwareRevision; __u8 hostName[64]; __u8 vendorString[64]; }; @@ -125,13 +125,13 @@ struct PptpStartSessionRequest { #define PPTP_START_UNKNOWN_PROTOCOL 5 struct PptpStartSessionReply { - __u16 protocolVersion; + __be16 protocolVersion; __u8 resultCode; __u8 generalErrorCode; - __u32 framingCapability; - __u32 bearerCapability; - __u16 maxChannels; - __u16 firmwareRevision; + __be32 framingCapability; + __be32 bearerCapability; + __be16 maxChannels; + __be16 firmwareRevision; __u8 hostName[64]; __u8 vendorString[64]; }; @@ -155,7 +155,7 @@ struct PptpStopSessionReply { }; struct PptpEchoRequest { - __u32 identNumber; + __be32 identNumber; }; /* PptpEchoReplyResultCode */ @@ -163,7 +163,7 @@ struct PptpEchoRequest { #define PPTP_ECHO_GENERAL_ERROR 2 struct PptpEchoReply { - __u32 identNumber; + __be32 identNumber; __u8 resultCode; __u8 generalErrorCode; __u16 reserved; @@ -180,16 +180,16 @@ struct PptpEchoReply { #define PPTP_DONT_CARE_BEARER_TYPE 3 struct PptpOutCallRequest { - __u16 callID; - __u16 callSerialNumber; - __u32 minBPS; - __u32 maxBPS; - __u32 bearerType; - __u32 framingType; - __u16 packetWindow; - __u16 packetProcDelay; + __be16 callID; + __be16 callSerialNumber; + __be32 minBPS; + __be32 maxBPS; + __be32 bearerType; + __be32 framingType; + __be16 packetWindow; + __be16 packetProcDelay; __u16 reserved1; - __u16 phoneNumberLength; + __be16 phoneNumberLength; __u16 reserved2; __u8 phoneNumber[64]; __u8 subAddress[64]; @@ -205,24 +205,24 @@ struct PptpOutCallRequest { #define PPTP_OUTCALL_DONT_ACCEPT 7 struct PptpOutCallReply { - __u16 callID; - __u16 peersCallID; + __be16 callID; + __be16 peersCallID; __u8 resultCode; __u8 generalErrorCode; - __u16 causeCode; - __u32 connectSpeed; - __u16 packetWindow; - __u16 packetProcDelay; - __u32 physChannelID; + __be16 causeCode; + __be32 connectSpeed; + __be16 packetWindow; + __be16 packetProcDelay; + __be32 physChannelID; }; struct PptpInCallRequest { - __u16 callID; - __u16 callSerialNumber; - __u32 callBearerType; - __u32 physChannelID; - __u16 dialedNumberLength; - __u16 dialingNumberLength; + __be16 callID; + __be16 callSerialNumber; + __be32 callBearerType; + __be32 physChannelID; + __be16 dialedNumberLength; + __be16 dialingNumberLength; __u8 dialedNumber[64]; __u8 dialingNumber[64]; __u8 subAddress[64]; @@ -234,54 +234,54 @@ struct PptpInCallRequest { #define PPTP_INCALL_DONT_ACCEPT 3 struct PptpInCallReply { - __u16 callID; - __u16 peersCallID; + __be16 callID; + __be16 peersCallID; __u8 resultCode; __u8 generalErrorCode; - __u16 packetWindow; - __u16 packetProcDelay; + __be16 packetWindow; + __be16 packetProcDelay; __u16 reserved; }; struct PptpInCallConnected { - __u16 peersCallID; + __be16 peersCallID; __u16 reserved; - __u32 connectSpeed; - __u16 packetWindow; - __u16 packetProcDelay; - __u32 callFramingType; + __be32 connectSpeed; + __be16 packetWindow; + __be16 packetProcDelay; + __be32 callFramingType; }; struct PptpClearCallRequest { - __u16 callID; + __be16 callID; __u16 reserved; }; struct PptpCallDisconnectNotify { - __u16 callID; + __be16 callID; __u8 resultCode; __u8 generalErrorCode; - __u16 causeCode; + __be16 causeCode; __u16 reserved; __u8 callStatistics[128]; }; struct PptpWanErrorNotify { - __u16 peersCallID; + __be16 peersCallID; __u16 reserved; - __u32 crcErrors; - __u32 framingErrors; - __u32 hardwareOverRuns; - __u32 bufferOverRuns; - __u32 timeoutErrors; - __u32 alignmentErrors; + __be32 crcErrors; + __be32 framingErrors; + __be32 hardwareOverRuns; + __be32 bufferOverRuns; + __be32 timeoutErrors; + __be32 alignmentErrors; }; struct PptpSetLinkInfo { - __u16 peersCallID; + __be16 peersCallID; __u16 reserved; - __u32 sendAccm; - __u32 recvAccm; + __be32 sendAccm; + __be32 recvAccm; }; diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h index 14dc0f7..20e43f0 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h @@ -17,7 +17,7 @@ union ip_conntrack_manip_proto u_int16_t all; struct { - u_int16_t port; + __be16 port; } tcp; struct { u_int16_t port; @@ -29,7 +29,7 @@ union ip_conntrack_manip_proto u_int16_t port; } sctp; struct { - u_int16_t key; /* key is 32bit, pptp only uses 16 */ + __be16 key; /* key is 32bit, pptp only uses 16 */ } gre; }; @@ -65,7 +65,7 @@ struct ip_conntrack_tuple u_int16_t port; } sctp; struct { - u_int16_t key; /* key is 32bit, + __be16 key; /* key is 32bit, * pptp only uses 16 */ } gre; } u; diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 1175879..8236ee0 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -223,8 +223,8 @@ static void pptp_destroy_siblings(struct ip_conntrack *ct) static inline int exp_gre(struct ip_conntrack *master, u_int32_t seq, - u_int16_t callid, - u_int16_t peer_callid) + __be16 callid, + __be16 peer_callid) { struct ip_conntrack_tuple inv_tuple; struct ip_conntrack_tuple exp_tuples[] = { @@ -263,7 +263,7 @@ exp_gre(struct ip_conntrack *master, exp_orig->mask.src.ip = 0xffffffff; exp_orig->mask.src.u.all = 0; exp_orig->mask.dst.u.all = 0; - exp_orig->mask.dst.u.gre.key = 0xffff; + exp_orig->mask.dst.u.gre.key = htons(0xffff); exp_orig->mask.dst.ip = 0xffffffff; exp_orig->mask.dst.protonum = 0xff; @@ -340,7 +340,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, unsigned int reqlen; union pptp_ctrl_union _pptpReq, *pptpReq; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; - u_int16_t msg, *cid, *pcid; + u_int16_t msg; + __be16 *cid, *pcid; u_int32_t seq; ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); @@ -551,7 +552,8 @@ pptp_outbound_pkt(struct sk_buff **pskb, unsigned int reqlen; union pptp_ctrl_union _pptpReq, *pptpReq; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; - u_int16_t msg, *cid, *pcid; + u_int16_t msg; + __be16 *cid, *pcid; ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); if (!ctlh) @@ -755,7 +757,7 @@ static struct ip_conntrack_helper pptp = { } }, .mask = { .src = { .ip = 0, - .u = { .tcp = { .port = 0xffff } } + .u = { .tcp = { .port = __constant_htons(0xffff) } } }, .dst = { .ip = 0, .u = { .all = 0 }, -- cgit v0.10.2 From a82b748930fce0dab22c64075c38c830ae116904 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 22 Sep 2005 23:45:44 -0700 Subject: [NETFILTER] remove unneeded structure definition from conntrack helper Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h index 50a761d..816144c 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h @@ -284,13 +284,6 @@ struct PptpSetLinkInfo { __be32 recvAccm; }; - -struct pptp_priv_data { - __u16 call_id; - __u16 mcall_id; - __u16 pcall_id; -}; - union pptp_ctrl_union { struct PptpStartSessionRequest sreq; struct PptpStartSessionReply srep; -- cgit v0.10.2 From 1dfbab59498d6f227c91988bab6c71af049a5333 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 22 Sep 2005 23:46:57 -0700 Subject: [NETFILTER] Fix conntrack event cache deadlock/oops This patch fixes a number of bugs. It cannot be reasonably split up in multiple fixes, since all bugs interact with each other and affect the same function: Bug #1: The event cache code cannot be called while a lock is held. Therefore, the call to ip_conntrack_event_cache() within ip_ct_refresh_acct() needs to be moved outside of the locked section. This fixes a number of 2.6.14-rcX oops and deadlock reports. Bug #2: We used to call ct_add_counters() for unconfirmed connections without holding a lock. Since the add operations are not atomic, we could race with another CPU. Bug #3: ip_ct_refresh_acct() lost REFRESH events in some cases where refresh (and the corresponding event) are desired, but no accounting shall be performed. Both, evenst and accounting implicitly depended on the skb parameter bein non-null. We now re-introduce a non-accounting "ip_ct_refresh()" variant to explicitly state the desired behaviour. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index bace72a..4ced387 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -332,11 +332,28 @@ extern void need_ip_conntrack(void); extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, const struct ip_conntrack_tuple *orig); +extern void __ip_ct_refresh_acct(struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + const struct sk_buff *skb, + unsigned long extra_jiffies, + int do_acct); + +/* Refresh conntrack for this many jiffies and do accounting */ +static inline void ip_ct_refresh_acct(struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + const struct sk_buff *skb, + unsigned long extra_jiffies) +{ + __ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1); +} + /* Refresh conntrack for this many jiffies */ -extern void ip_ct_refresh_acct(struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - const struct sk_buff *skb, - unsigned long extra_jiffies); +static inline void ip_ct_refresh(struct ip_conntrack *ct, + const struct sk_buff *skb, + unsigned long extra_jiffies) +{ + __ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0); +} /* These are for NAT. Icky. */ /* Update TCP window tracking data when NAT mangles the packet */ diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index dc20881..fa3f914 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -65,7 +65,7 @@ static int help(struct sk_buff **pskb, /* increase the UDP timeout of the master connection as replies from * Amanda clients to the server can be quite delayed */ - ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ); + ip_ct_refresh(ct, *pskb, master_timeout * HZ); /* No data? */ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index c1f82e0..ea65dd3 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1112,45 +1112,46 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) synchronize_net(); } -static inline void ct_add_counters(struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - const struct sk_buff *skb) -{ -#ifdef CONFIG_IP_NF_CT_ACCT - if (skb) { - ct->counters[CTINFO2DIR(ctinfo)].packets++; - ct->counters[CTINFO2DIR(ctinfo)].bytes += - ntohs(skb->nh.iph->tot_len); - } -#endif -} - -/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */ -void ip_ct_refresh_acct(struct ip_conntrack *ct, +/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */ +void __ip_ct_refresh_acct(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, const struct sk_buff *skb, - unsigned long extra_jiffies) + unsigned long extra_jiffies, + int do_acct) { + int do_event = 0; + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + IP_NF_ASSERT(skb); + + write_lock_bh(&ip_conntrack_lock); /* If not in hash table, timer will not be active yet */ if (!is_confirmed(ct)) { ct->timeout.expires = extra_jiffies; - ct_add_counters(ct, ctinfo, skb); + do_event = 1; } else { - write_lock_bh(&ip_conntrack_lock); /* Need del_timer for race avoidance (may already be dying). */ if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; add_timer(&ct->timeout); - /* FIXME: We loose some REFRESH events if this function - * is called without an skb. I'll fix this later -HW */ - if (skb) - ip_conntrack_event_cache(IPCT_REFRESH, skb); + do_event = 1; } - ct_add_counters(ct, ctinfo, skb); - write_unlock_bh(&ip_conntrack_lock); } + +#ifdef CONFIG_IP_NF_CT_ACCT + if (do_acct) { + ct->counters[CTINFO2DIR(ctinfo)].packets++; + ct->counters[CTINFO2DIR(ctinfo)].bytes += + ntohs(skb->nh.iph->tot_len); + } +#endif + + write_unlock_bh(&ip_conntrack_lock); + + /* must be unlocked when calling event cache */ + if (do_event) + ip_conntrack_event_cache(IPCT_REFRESH, skb); } #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 8236ee0..926a668 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -172,7 +172,6 @@ static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) DEBUGP("setting timeout of conntrack %p to 0\n", sibling); sibling->proto.gre.timeout = 0; sibling->proto.gre.stream_timeout = 0; - /* refresh_acct will not modify counters if skb == NULL */ if (del_timer(&sibling->timeout)) sibling->timeout.function((unsigned long)sibling); ip_conntrack_put(sibling); diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c index 71ef19d..577bac2 100644 --- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c +++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c @@ -91,7 +91,7 @@ static int help(struct sk_buff **pskb, ip_conntrack_expect_related(exp); ip_conntrack_expect_put(exp); - ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ); + ip_ct_refresh(ct, *pskb, timeout * HZ); out: return NF_ACCEPT; } diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index d3c7808..dd476b1 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -989,7 +989,7 @@ EXPORT_SYMBOL(need_ip_conntrack); EXPORT_SYMBOL(ip_conntrack_helper_register); EXPORT_SYMBOL(ip_conntrack_helper_unregister); EXPORT_SYMBOL(ip_ct_iterate_cleanup); -EXPORT_SYMBOL(ip_ct_refresh_acct); +EXPORT_SYMBOL(__ip_ct_refresh_acct); EXPORT_SYMBOL(ip_conntrack_expect_alloc); EXPORT_SYMBOL(ip_conntrack_expect_put); -- cgit v0.10.2 From eb0e0076878a4f9e8e6e7e524ded0d6f7d4a6130 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Thu, 22 Sep 2005 23:48:38 -0700 Subject: [SCTP]: Fix SCTP_SHUTDOWN notifications. Fix to allow SCTP_SHUTDOWN notifications to be received on 1-1 style SCTP SOCK_STREAM sockets. Add SCTP_SHUTDOWN notification to the receive queue before updating the state of the association. Signed-off-by: Sridhar Samudrala Signed-off-by: Neil Horman Signed-off-by: David S. Miller diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 86073df..505c7de1 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2414,6 +2414,17 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); chunk->subh.shutdown_hdr = sdh; + /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT + * When a peer sends a SHUTDOWN, SCTP delivers this notification to + * inform the application that it should cease sending data. + */ + ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); + if (!ev) { + disposition = SCTP_DISPOSITION_NOMEM; + goto out; + } + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + /* Upon the reception of the SHUTDOWN, the peer endpoint shall * - enter the SHUTDOWN-RECEIVED state, * - stop accepting new data from its SCTP user @@ -2439,17 +2450,6 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack)); - /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT - * When a peer sends a SHUTDOWN, SCTP delivers this notification to - * inform the application that it should cease sending data. - */ - ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); - if (!ev) { - disposition = SCTP_DISPOSITION_NOMEM; - goto out; - } - sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); - out: return disposition; } -- cgit v0.10.2 From 9389d79fbf9a0167ff2de87e8796c6bb803219bf Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 23 Sep 2005 05:18:45 -0400 Subject: [PATCH] 8390 Tx fix for non i386 machines While this is true, E8390_CMD is zero on i386, and thus there should be no effect for these machines. Machines like Mac, Amiga etc. which use Alan's clever register mapping may have a non-zero E8390_CMD and result in bogus "transmitter busy" type messages from this bug. Fixes BUG# 3991. diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 6d76f3a..f870274 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -1094,7 +1094,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); - if (inb_p(e8390_base) & E8390_TRANS) + if (inb_p(e8390_base + E8390_CMD) & E8390_TRANS) { printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", dev->name); -- cgit v0.10.2 From 715dc636b64b57aee7aee7e8b5bf4f5267a6df48 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Fri, 23 Sep 2005 11:24:28 +0100 Subject: NTFS: Change ntfs_cluster_free() to require a write locked runlist on entry since we otherwise get into a lock reversal deadlock if a read locked runlist is passed in. In the process also change it to take an ntfs inode instead of a vfs inode as parameter. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index ee8665f..574896f 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -25,6 +25,10 @@ ToDo/Notes: 2.1.25-WIP - Fix sparse warnings that have crept in over time. + - Change ntfs_cluster_free() to require a write locked runlist on entry + since we otherwise get into a lock reversal deadlock if a read locked + runlist is passed in. In the process also change it to take an ntfs + inode instead of a vfs inode as parameter. 2.1.24 - Lots of bug fixes and support more clean journal states. diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 894b2b8..a3ce2c0 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.24\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.25-WIP\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 7b59342..5af3bf0 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -779,14 +779,13 @@ out: /** * __ntfs_cluster_free - free clusters on an ntfs volume - * @vi: vfs inode whose runlist describes the clusters to free - * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters + * @ni: ntfs inode whose runlist describes the clusters to free + * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters * @count: number of clusters to free or -1 for all clusters - * @write_locked: true if the runlist is locked for writing * @is_rollback: true if this is a rollback operation * * Free @count clusters starting at the cluster @start_vcn in the runlist - * described by the vfs inode @vi. + * described by the vfs inode @ni. * * If @count is -1, all clusters from @start_vcn to the end of the runlist are * deallocated. Thus, to completely free all clusters in a runlist, use @@ -801,31 +800,28 @@ out: * Return the number of deallocated clusters (not counting sparse ones) on * success and -errno on error. * - * Locking: - The runlist described by @vi must be locked on entry and is - * locked on return. Note if the runlist is locked for reading the - * lock may be dropped and reacquired. Note the runlist may be - * modified when needed runlist fragments need to be mapped. + * Locking: - The runlist described by @ni must be locked for writing on entry + * and is locked on return. Note the runlist may be modified when + * needed runlist fragments need to be mapped. * - The volume lcn bitmap must be unlocked on entry and is unlocked * on return. * - This function takes the volume lcn bitmap lock for writing and * modifies the bitmap contents. */ -s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, - const BOOL write_locked, const BOOL is_rollback) +s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, + const BOOL is_rollback) { s64 delta, to_free, total_freed, real_freed; - ntfs_inode *ni; ntfs_volume *vol; struct inode *lcnbmp_vi; runlist_element *rl; int err; - BUG_ON(!vi); + BUG_ON(!ni); ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " - "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn, + "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn, (unsigned long long)count, is_rollback ? " (rollback)" : ""); - ni = NTFS_I(vi); vol = ni->vol; lcnbmp_vi = vol->lcnbmp_ino; BUG_ON(!lcnbmp_vi); @@ -843,7 +839,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, total_freed = real_freed = 0; - rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked); + rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE); if (IS_ERR(rl)) { if (!is_rollback) ntfs_error(vol->sb, "Failed to find first runlist " @@ -897,7 +893,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, /* Attempt to map runlist. */ vcn = rl->vcn; - rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked); + rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE); if (IS_ERR(rl)) { err = PTR_ERR(rl); if (!is_rollback) @@ -965,8 +961,7 @@ err_out: * If rollback fails, set the volume errors flag, emit an error * message, and return the error code. */ - delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked, - TRUE); + delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE); if (delta < 0) { ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " "inconsistent metadata! Unmount and run " diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h index e4d7fb9..a6a8827 100644 --- a/fs/ntfs/lcnalloc.h +++ b/fs/ntfs/lcnalloc.h @@ -2,7 +2,7 @@ * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the * Linux-NTFS project. * - * Copyright (c) 2004 Anton Altaparmakov + * Copyright (c) 2004-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -28,6 +28,7 @@ #include #include "types.h" +#include "inode.h" #include "runlist.h" #include "volume.h" @@ -42,18 +43,17 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, const s64 count, const LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone); -extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, - s64 count, const BOOL write_locked, const BOOL is_rollback); +extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, + s64 count, const BOOL is_rollback); /** * ntfs_cluster_free - free clusters on an ntfs volume - * @vi: vfs inode whose runlist describes the clusters to free - * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters + * @ni: ntfs inode whose runlist describes the clusters to free + * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters * @count: number of clusters to free or -1 for all clusters - * @write_locked: true if the runlist is locked for writing * * Free @count clusters starting at the cluster @start_vcn in the runlist - * described by the vfs inode @vi. + * described by the ntfs inode @ni. * * If @count is -1, all clusters from @start_vcn to the end of the runlist are * deallocated. Thus, to completely free all clusters in a runlist, use @@ -65,19 +65,18 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, * Return the number of deallocated clusters (not counting sparse ones) on * success and -errno on error. * - * Locking: - The runlist described by @vi must be locked on entry and is - * locked on return. Note if the runlist is locked for reading the - * lock may be dropped and reacquired. Note the runlist may be - * modified when needed runlist fragments need to be mapped. + * Locking: - The runlist described by @ni must be locked for writing on entry + * and is locked on return. Note the runlist may be modified when + * needed runlist fragments need to be mapped. * - The volume lcn bitmap must be unlocked on entry and is unlocked * on return. * - This function takes the volume lcn bitmap lock for writing and * modifies the bitmap contents. */ -static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn, - s64 count, const BOOL write_locked) +static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, + s64 count) { - return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE); + return __ntfs_cluster_free(ni, start_vcn, count, FALSE); } extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 2c32b84..247586d 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1953,7 +1953,7 @@ restore_undo_alloc: a = ctx->attr; a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); undo_alloc: - if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) { + if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) { ntfs_error(vol->sb, "Failed to free clusters from mft data " "attribute.%s", es); NVolSetErrors(vol); -- cgit v0.10.2 From 12f44f46bc9c6dc79255e661b085797af395d8da Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Thu, 22 Sep 2005 21:06:31 -0700 Subject: [PATCH] pci: fixup parent subordinate busnr I believe the change that broke things is introduction of pci_fixup_parent_subordinate_busnr(). The patch here does two things: - hunk #1 should fix the problems you've seen when you boot without additional "pci" kernel options; - hunk #2 supposedly fixes boot with "pci=assign-busses" option which otherwise hangs Acer TM81xx machines as reported. Please try this with and without "pci=assign-busses". If it boots, I'd like to see 'lspci -vvx' for both cases. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c77d5b1..0057864 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -402,6 +402,12 @@ static void pci_enable_crs(struct pci_dev *dev) static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) { struct pci_bus *parent = child->parent; + + /* Attempts to fix that up are really dangerous unless + we're going to re-assign all bus numbers. */ + if (!pcibios_assign_all_busses()) + return; + while (parent->parent && parent->subordinate < max) { parent->subordinate = max; pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max); @@ -478,8 +484,18 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max * We need to assign a number to this bus which we always * do in the second pass. */ - if (!pass) + if (!pass) { + if (pcibios_assign_all_busses()) + /* Temporarily disable forwarding of the + configuration cycles on all bridges in + this bus segment to avoid possible + conflicts in the second pass between two + bridges programmed with overlapping + bus ranges. */ + pci_write_config_dword(dev, PCI_PRIMARY_BUS, + buses & ~0xffffff); return max; + } /* Clear errors */ pci_write_config_word(dev, PCI_STATUS, 0xffff); -- cgit v0.10.2 From ede1327ea4ca8019ec6df24b3e837def091c26b8 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 30 Aug 2005 20:10:14 -0700 Subject: [PATCH] cifs: Add support for suspend cifsd had been preventing software suspend from completing. Signed-off-by: pavel@suse.de Signed-off-by: Steve French lightly modified Signed-off-by: Linus Torvalds diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8cc23e7..1ebf7da 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -781,6 +781,8 @@ static int cifs_oplock_thread(void * dummyarg) oplockThread = current; do { + if (try_to_freeze()) + continue; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1*HZ); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2335f14..4736015 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -344,6 +344,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } while (server->tcpStatus != CifsExiting) { + if (try_to_freeze()) + continue; if (bigbuf == NULL) { bigbuf = cifs_buf_get(); if(bigbuf == NULL) { -- cgit v0.10.2 From 1c9ea5db001142a96fec8fed0f92f26892a1b6ac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 23 Sep 2005 11:54:43 -0700 Subject: [SPARC64]: Kill unused variable in setup_arch() 'highest_paddr' is set, but never actually used. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 0296cb0..f4345d8 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -496,7 +496,6 @@ extern void paging_init(void); void __init setup_arch(char **cmdline_p) { - unsigned long highest_paddr; int i; /* Initialize PROM console and command line. */ @@ -519,11 +518,7 @@ void __init setup_arch(char **cmdline_p) idprom_init(); (void) prom_probe_memory(); - /* In paging_init() we tip off this value to see if we need - * to change init_mm.pgd to point to the real alias mapping. - */ phys_base = 0xffffffffffffffffUL; - highest_paddr = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { unsigned long top; @@ -531,8 +526,6 @@ void __init setup_arch(char **cmdline_p) phys_base = sp_banks[i].base_addr; top = sp_banks[i].base_addr + sp_banks[i].num_bytes; - if (highest_paddr < top) - highest_paddr = top; } pfn_base = phys_base >> PAGE_SHIFT; -- cgit v0.10.2 From 898cf0ecb7959db97d71cbce19685ce73a28d47c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 23 Sep 2005 11:59:44 -0700 Subject: [SPARC64]: Mark functions called by paging_init() as __init. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index e0b9eeb..cf747372 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -410,7 +410,7 @@ unsigned long prom_virt_to_phys(unsigned long promva, int *error) * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte * scheme (also, see rant in inherit_locked_prom_mappings()). */ -static void build_obp_range(unsigned long start, unsigned long end, unsigned long data) +static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data) { unsigned long vaddr; @@ -454,7 +454,7 @@ static inline int in_obp_range(unsigned long vaddr) } #define OBP_PMD_SIZE 2048 -static void build_obp_pgtable(int prom_trans_ents) +static void __init build_obp_pgtable(int prom_trans_ents) { unsigned long i; @@ -480,7 +480,7 @@ static void build_obp_pgtable(int prom_trans_ents) /* Read OBP translations property into 'prom_trans[]'. * Return the number of entries. */ -static int read_obp_translations(void) +static int __init read_obp_translations(void) { int n, node; @@ -505,7 +505,7 @@ static int read_obp_translations(void) return n; } -static void remap_kernel(void) +static void __init remap_kernel(void) { unsigned long phys_page, tte_vaddr, tte_data; int tlb_ent = sparc64_highest_locked_tlbent(); @@ -531,7 +531,7 @@ static void remap_kernel(void) } } -static void inherit_prom_mappings(void) +static void __init inherit_prom_mappings(void) { int n; @@ -1604,7 +1604,7 @@ void __init mem_init(void) cheetah_ecache_flush_init(); } -void free_initmem (void) +void free_initmem(void) { unsigned long addr, initend; -- cgit v0.10.2 From 188a1eafa03aaa5e5fe6f53e637e704cd2c31c7c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Sep 2005 13:22:21 -0700 Subject: Make sure SIGKILL gets proper respect Bhavesh P. Davda noticed that SIGKILL wouldn't properly kill a process under just the right cicumstances: a stopped task that already had another signal queued would get the SIGKILL queued onto the shared queue, and there it would remain until SIGCONT. This simplifies the signal acceptance logic, and fixes the bug in the process. Losely based on an earlier patch by Bhavesh. Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index b92c3c9..5a27470 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -936,34 +936,31 @@ force_sig_specific(int sig, struct task_struct *t) * as soon as they're available, so putting the signal on the shared queue * will be equivalent to sending it to one such thread. */ -#define wants_signal(sig, p, mask) \ - (!sigismember(&(p)->blocked, sig) \ - && !((p)->state & mask) \ - && !((p)->flags & PF_EXITING) \ - && (task_curr(p) || !signal_pending(p))) - +static inline int wants_signal(int sig, struct task_struct *p) +{ + if (sigismember(&p->blocked, sig)) + return 0; + if (p->flags & PF_EXITING) + return 0; + if (sig == SIGKILL) + return 1; + if (p->state & (TASK_STOPPED | TASK_TRACED)) + return 0; + return task_curr(p) || !signal_pending(p); +} static void __group_complete_signal(int sig, struct task_struct *p) { - unsigned int mask; struct task_struct *t; /* - * Don't bother traced and stopped tasks (but - * SIGKILL will punch through that). - */ - mask = TASK_STOPPED | TASK_TRACED; - if (sig == SIGKILL) - mask = 0; - - /* * Now find a thread we can wake up to take the signal off the queue. * * If the main thread wants the signal, it gets first crack. * Probably the least surprising to the average bear. */ - if (wants_signal(sig, p, mask)) + if (wants_signal(sig, p)) t = p; else if (thread_group_empty(p)) /* @@ -981,7 +978,7 @@ __group_complete_signal(int sig, struct task_struct *p) t = p->signal->curr_target = p; BUG_ON(t->tgid != p->tgid); - while (!wants_signal(sig, t, mask)) { + while (!wants_signal(sig, t)) { t = next_thread(t); if (t == p->signal->curr_target) /* -- cgit v0.10.2 From a3b5f0d43863402b03b3af9a7eaec0037a823374 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Fri, 23 Sep 2005 13:24:05 -0700 Subject: [PATCH] hisax: remove URB_ASYNC_UNLINK usb_unlink_urb is always async now, so URB_ASYNC_UNLINK was removed from core USB and we must do as well. Signed-off-by: Karsten Keil Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 0a2536d..657817a 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -209,9 +209,7 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) bcs->mode = mode; // Cancel all USB transfers on this B channel - b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[0]); - b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(b_out->urb[1]); b_out->busy = 0; diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index ffd5b2d..89fbeb5 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -645,9 +645,7 @@ void st5481_in_mode(struct st5481_in *in, int mode) in->mode = mode; - in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[0]); - in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(in->urb[1]); if (in->mode != L1_MODE_NULL) { -- cgit v0.10.2 From 2601c2e278863cd48c01bce1377b4c9747893025 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Sep 2005 13:24:06 -0700 Subject: [PATCH] atyfb c99 fix - fix this: drivers/video/aty/xlinit.c: In function `atyfb_xl_init': drivers/video/aty/xlinit.c:256: warning: ISO C90 forbids mixed declarations and code - repair some kooky coding style - Use ARRAY_SIZE() Cc: Tom 'spot' Callaway Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c index 0bea0d8..a085cbf 100644 --- a/drivers/video/aty/xlinit.c +++ b/drivers/video/aty/xlinit.c @@ -253,9 +253,11 @@ int atyfb_xl_init(struct fb_info *info) aty_st_le32(0xFC, 0x00000000, par); #if defined (CONFIG_FB_ATY_GENERIC_LCD) - int i; - for (i=0; i Date: Fri, 23 Sep 2005 13:24:07 -0700 Subject: [PATCH] ppc64: Fix huge pages MMU mapping bug Current kernel has a couple of sneaky bugs in the ppc64 hugetlb code that cause huge pages to be potentially left stale in the hash table and TLBs (improperly invalidated), with all the nasty consequences that can have. One is that we forgot to set the "secondary" bit in the hash PTEs when hashing a huge page in the secondary bucket (fortunately very rare). The other one is on non-LPAR machines (like Apple G5s), flush_hash_range() which is used to flush a batch of PTEs simply did not work for huge pages. Historically, our huge page code didn't batch, but this was changed without fixing this routine. This patch fixes both. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c index 7626bb5..eb1bbb5 100644 --- a/arch/ppc64/mm/hash_native.c +++ b/arch/ppc64/mm/hash_native.c @@ -343,9 +343,7 @@ static void native_flush_hash_range(unsigned long context, hpte_t *hptep; unsigned long hpte_v; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - - /* XXX fix for large ptes */ - unsigned long large = 0; + unsigned long large; local_irq_save(flags); @@ -358,6 +356,7 @@ static void native_flush_hash_range(unsigned long context, va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); batch->vaddr[j] = va; + large = pte_huge(batch->pte[i]); if (large) vpn = va >> HPAGE_SHIFT; else diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c index 338771e..0ea0994 100644 --- a/arch/ppc64/mm/hugetlbpage.c +++ b/arch/ppc64/mm/hugetlbpage.c @@ -710,10 +710,13 @@ repeat: hpte_group = ((~hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; slot = ppc_md.hpte_insert(hpte_group, va, prpn, - HPTE_V_LARGE, rflags); + HPTE_V_LARGE | + HPTE_V_SECONDARY, + rflags); if (slot == -1) { if (mftb() & 0x1) - hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; + hpte_group = ((hash & htab_hash_mask) * + HPTES_PER_GROUP)&~0x7UL; ppc_md.hpte_remove(hpte_group); goto repeat; -- cgit v0.10.2 From e7c965084392e23a3494f0247c75795360a3fa0d Mon Sep 17 00:00:00 2001 From: Hironobu Ishii Date: Fri, 23 Sep 2005 13:24:08 -0700 Subject: [PATCH] ipmi_msghandler: inconsistent spin_lock usage I found an inconsistent spin_lock usage in ipmi_smi_msg_received. Signed-off-by: Hironobu Ishii Cc: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 463351d..32fa82c 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2620,7 +2620,7 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); if (!list_empty(&(intf->waiting_msgs))) { list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock(&(intf->waiting_msgs_lock)); + spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); goto out_unlock; } spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); @@ -2629,9 +2629,9 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, if (rv > 0) { /* Could not handle the message now, just add it to a list to handle later. */ - spin_lock(&(intf->waiting_msgs_lock)); + spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock(&(intf->waiting_msgs_lock)); + spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); } else if (rv == 0) { ipmi_free_smi_msg(msg); } -- cgit v0.10.2 From 86513e726b494796175b6c4fdd705797f01b0ca2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 23 Sep 2005 13:24:10 -0700 Subject: [PATCH] documentation: sparse no longer uses bk, but git Signed-off-by: Harald Welte Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 5df44dc..1829009 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -51,9 +51,9 @@ or you don't get any checking at all. Where to get sparse ~~~~~~~~~~~~~~~~~~~ -With BK, you can just get it from +With git, you can just get it from - bk://sparse.bkbits.net/sparse + rsync://rsync.kernel.org/pub/scm/devel/sparse/sparse.git and DaveJ has tar-balls at -- cgit v0.10.2 From dbdb90450059e17e8e005ebd3ce0a1fd6008a0c8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 23 Sep 2005 13:24:10 -0700 Subject: [PATCH] revert oversized kmalloc check As davem points out, this wasn't such a great idea. There may be some code which does: size = 1024*1024; while (kmalloc(size, ...) == 0) size /= 2; which will now explode. Cc: "David S. Miller" Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index ad113c4..c9adfce 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2907,7 +2907,8 @@ void *__kmalloc(size_t size, unsigned int __nocast flags) * functions. */ cachep = __find_general_cachep(size, flags); - BUG_ON(!cachep); /* Allocation size too large for kmalloc */ + if (unlikely(cachep == NULL)) + return NULL; return __cache_alloc(cachep, flags); } EXPORT_SYMBOL(__kmalloc); -- cgit v0.10.2 From 73394322a4bf4108847ba3c2eee33a81b1b44450 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 23 Sep 2005 21:49:58 +0100 Subject: [ARM] Fix context switch with ARMv6 + TLS We accidentally corrupted the TLS value when clearing out the ARMv6 exclusive monitor. Avoid doing so. Signed-off-by: Russell King diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7152bfb..93b5e8e 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -537,7 +537,7 @@ ENTRY(__switch_to) #ifdef CONFIG_CPU_MPCORE clrex #else - strex r3, r4, [ip] @ Clear exclusive monitor + strex r5, r4, [ip] @ Clear exclusive monitor #endif #endif #if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) -- cgit v0.10.2 From c8868611389aa28e0e5e0d63f468727781eac68c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 23 Sep 2005 09:08:30 -0700 Subject: [PATCH] skge: fix Yukon-Lite A0 workaround This is one of those workarounds sucked over from sk98lin driver. The skge driver needs to detect the Yukon-Lite A0 chip properly, and turn of Rx FIFO Flush. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik diff --git a/drivers/net/skge.c b/drivers/net/skge.c index ae1996a..fd398da 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1643,6 +1643,22 @@ static void yukon_reset(struct skge_hw *hw, int port) | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); } +/* Apparently, early versions of Yukon-Lite had wrong chip_id? */ +static int is_yukon_lite_a0(struct skge_hw *hw) +{ + u32 reg; + int ret; + + if (hw->chip_id != CHIP_ID_YUKON) + return 0; + + reg = skge_read32(hw, B2_FAR); + skge_write8(hw, B2_FAR + 3, 0xff); + ret = (skge_read8(hw, B2_FAR + 3) != 0); + skge_write32(hw, B2_FAR, reg); + return ret; +} + static void yukon_mac_init(struct skge_hw *hw, int port) { struct skge_port *skge = netdev_priv(hw->dev[port]); @@ -1758,9 +1774,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* Configure Rx MAC FIFO */ skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) + + /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ + if (is_yukon_lite_a0(hw)) reg &= ~GMF_RX_F_FL_ON; + skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); /* -- cgit v0.10.2 From f993724210744a9b07cf5496808828c4da6ab6df Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 24 Sep 2005 10:12:47 +0100 Subject: [SERIAL] Remove unused variable in clps711x.c Signed-off-by: Russell King diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index 78c1f36..87ef368 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -98,7 +98,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; - unsigned int status, ch, flg, ignored = 0; + unsigned int status, ch, flg; status = clps_readl(SYSFLG(port)); while (!(status & SYSFLG_URXFE)) { -- cgit v0.10.2 From 6b9ea4213e3a9c9b8de29a001a2b8d8799cbc1c9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 24 Sep 2005 10:24:37 +0100 Subject: [MFD] Fix "bious one-bit signed bitfield" errors ucb1x00-ts declared a couple of one-bit 'int' bitfields. Make them unsigned. Signed-off-by: Russell King diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index a851d65..a260f83 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c @@ -48,8 +48,8 @@ struct ucb1x00_ts { u16 x_res; u16 y_res; - int restart:1; - int adcsync:1; + unsigned int restart:1; + unsigned int adcsync:1; }; static int adcsync; -- cgit v0.10.2 From d2f607484f8210cf19b1730dee26d426a5a770a5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 24 Sep 2005 10:42:06 +0100 Subject: [ARM] Fix compiler warnings for memcpy_toio/memcpy_fromio/memset_io Add 'volatile' to the __iomem pointers for these functions as per x86. Signed-off-by: Russell King diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index 6c20c11..1f6822d 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -7,7 +7,7 @@ * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void _memcpy_fromio(void *to, void __iomem *from, size_t count) +void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) { unsigned char *t = to; while (count) { @@ -22,7 +22,7 @@ void _memcpy_fromio(void *to, void __iomem *from, size_t count) * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void _memcpy_toio(void __iomem *to, const void *from, size_t count) +void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) { const unsigned char *f = from; while (count) { @@ -37,7 +37,7 @@ void _memcpy_toio(void __iomem *to, const void *from, size_t count) * "memset" on IO memory space. * This needs to be optimized. */ -void _memset_io(void __iomem *dst, int c, size_t count) +void _memset_io(volatile void __iomem *dst, int c, size_t count) { while (count) { count--; diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index cfa71a0..5c4ae8f 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -136,9 +136,9 @@ extern void __readwrite_bug(const char *fn); /* * String version of IO memory access ops: */ -extern void _memcpy_fromio(void *, void __iomem *, size_t); -extern void _memcpy_toio(void __iomem *, const void *, size_t); -extern void _memset_io(void __iomem *, int, size_t); +extern void _memcpy_fromio(void *, const volatile void __iomem *, size_t); +extern void _memcpy_toio(volatile void __iomem *, const void *, size_t); +extern void _memset_io(volatile void __iomem *, int, size_t); #define mmiowb() -- cgit v0.10.2 From ff13f98b97cb6c5a2d201dfa4db0a2fd0b4d9d50 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 24 Sep 2005 02:02:29 -0500 Subject: [PATCH] Input: check switch bitmap when matching handlers The wwitch bitmap was added to input_device_id structure and we should check it when matching handlers and input devices. Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Torvalds diff --git a/drivers/input/input.c b/drivers/input/input.c index 88636a2..14ae558 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -308,6 +308,7 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st MATCH_BIT(ledbit, LED_MAX); MATCH_BIT(sndbit, SND_MAX); MATCH_BIT(ffbit, FF_MAX); + MATCH_BIT(swbit, SW_MAX); return id; } -- cgit v0.10.2 From d67b24c40f81823abe5c1eb808bba1038969142b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 24 Sep 2005 16:52:03 -0700 Subject: [NETFILTER]: Fix ip[6]t_NFQUEUE Kconfig dependency We have to introduce a separate Kconfig menu entry for the NFQUEUE targets. They cannot "just" depend on nfnetlink_queue, since nfnetlink_queue could be linked into the kernel, whereas iptables can be a module. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 3cf9b45..2cd7e7d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -537,6 +537,17 @@ config IP_NF_TARGET_TCPMSS To compile it as a module, choose M here. If unsure, say N. +config IP_NF_TARGET_NFQUEUE + tristate "NFQUEUE Target Support" + depends on IP_NF_IPTABLES + help + This Target replaced the old obsolete QUEUE target. + + As opposed to QUEUE, it supports 65535 different queues, + not just one. + + To compile it as a module, choose M here. If unsure, say N. + # NAT + specific targets config IP_NF_NAT tristate "Full NAT" diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 3d45d3c..8900253 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o +obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o # generic ARP tables obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o @@ -101,4 +102,3 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o -obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ipt_NFQUEUE.o diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 216fbe1a..bb7ccfe 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -209,6 +209,17 @@ config IP6_NF_TARGET_REJECT To compile it as a module, choose M here. If unsure, say N. +config IP6_NF_TARGET_NFQUEUE + tristate "NFQUEUE Target Support" + depends on IP_NF_IPTABLES + help + This Target replaced the old obsolete QUEUE target. + + As opposed to QUEUE, it supports 65535 different queues, + not just one. + + To compile it as a module, choose M here. If unsure, say N. + # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index bd9a16a..2b2c370 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -21,9 +21,9 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o +obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o -obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ip6t_NFQUEUE.o -- cgit v0.10.2 From 45fc3b11f1d419ed6c636e5ca84472d9805f520e Mon Sep 17 00:00:00 2001 From: Amos Waterland Date: Sat, 24 Sep 2005 16:53:16 -0700 Subject: [NET]: Protect neigh_stat_seq_fops by CONFIG_PROC_FS From: Amos Waterland If CONFIG_PROC_FS is not selected, the compiler emits this warning: net/core/neighbour.c:64: warning: `neigh_stat_seq_fops' defined but not used Which is correct, because neigh_stat_seq_fops is in fact only initialized and used by code that is protected by CONFIG_PROC_FS. So this patch fixes that up. Signed-off-by: Amos Waterland Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 39fc55e..5f16008 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -61,7 +61,9 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); static struct neigh_table *neigh_tables; +#ifdef CONFIG_PROC_FS static struct file_operations neigh_stat_seq_fops; +#endif /* Neighbour hash table buckets are protected with rwlock tbl->lock. -- cgit v0.10.2 From 15166fadb0308496bbff50c08ed5fe6a18d5cc4f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 24 Sep 2005 16:54:50 -0700 Subject: [IRDA]: Fix memory leak in irttp_init() Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 6602d90..1df6487 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -100,6 +100,7 @@ int __init irttp_init(void) if (!irttp->tsaps) { IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n", __FUNCTION__); + kfree(irttp); return -ENOMEM; } -- cgit v0.10.2 From 8689c07e47e928f8e329f667df8cf697a37425dd Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 24 Sep 2005 16:55:17 -0700 Subject: [IRDA]: *irttp cleanup * Remove useless comment. * Remove useless assertions. * Remove useless comparison. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 1df6487..8aff254 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -38,7 +38,7 @@ #include #include -static struct irttp_cb *irttp = NULL; +static struct irttp_cb *irttp; static void __irttp_close_tsap(struct tsap_cb *self); @@ -86,12 +86,9 @@ static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 }; */ int __init irttp_init(void) { - /* Initialize the irttp structure. */ - if (irttp == NULL) { - irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL); - if (irttp == NULL) - return -ENOMEM; - } + irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL); + if (irttp == NULL) + return -ENOMEM; memset(irttp, 0, sizeof(struct irttp_cb)); irttp->magic = TTP_MAGIC; @@ -116,7 +113,6 @@ int __init irttp_init(void) void __exit irttp_cleanup(void) { /* Check for main structure */ - IRDA_ASSERT(irttp != NULL, return;); IRDA_ASSERT(irttp->magic == TTP_MAGIC, return;); /* @@ -383,7 +379,6 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) struct lsap_cb *lsap; notify_t ttp_notify; - IRDA_ASSERT(irttp != NULL, return NULL;); IRDA_ASSERT(irttp->magic == TTP_MAGIC, return NULL;); /* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to @@ -1881,8 +1876,6 @@ static int irttp_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc = -ENOMEM; struct irttp_iter_state *s; - - IRDA_ASSERT(irttp != NULL, return -EINVAL;); s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) -- cgit v0.10.2 From 8ddec7460d2f5db3ac35812c03676b1473d1d668 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 24 Sep 2005 16:56:08 -0700 Subject: [NETFILTER] ip_conntrack: Update event cache when status changes The GRE, SCTP and TCP protocol helpers did not call ip_conntrack_event_cache() when updating ct->status. This patch adds the respective calls. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c index de3cb9d..744abb9 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -247,6 +247,7 @@ static int gre_packet(struct ip_conntrack *ct, ct->proto.gre.stream_timeout); /* Also, more likely to be important, and not a probe. */ set_bit(IPS_ASSURED_BIT, &ct->status); + ip_conntrack_event_cache(IPCT_STATUS, skb); } else ip_ct_refresh_acct(ct, conntrackinfo, skb, ct->proto.gre.timeout); diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index a875f35..59a4a01 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -416,6 +416,7 @@ static int sctp_packet(struct ip_conntrack *conntrack, && newconntrack == SCTP_CONNTRACK_ESTABLISHED) { DEBUGP("Setting assured bit\n"); set_bit(IPS_ASSURED_BIT, &conntrack->status); + ip_conntrack_event_cache(IPCT_STATUS, skb); } return NF_ACCEPT; diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 1985abc..121760d 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -1014,7 +1014,8 @@ static int tcp_packet(struct ip_conntrack *conntrack, /* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV or a valid answer for a picked up connection. */ - set_bit(IPS_ASSURED_BIT, &conntrack->status); + set_bit(IPS_ASSURED_BIT, &conntrack->status); + ip_conntrack_event_cache(IPCT_STATUS, skb); } ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout); -- cgit v0.10.2 From 52f26deb7c67d5f34910660200b925c1a2b8df8c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 24 Sep 2005 23:06:14 -0700 Subject: [SPARC64]: Fix mask formation in tomatillo_wsync_handler() "1" needs to be "1UL", this is a 64-bit mask we're creating. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 331382e..cae5b61 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -330,7 +330,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino) static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) { unsigned long sync_reg = (unsigned long) _arg2; - u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO); + u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO); u64 val; int limit; -- cgit v0.10.2 From 49bfd8db4a39ea14fb3780b162012b4b3611fce8 Mon Sep 17 00:00:00 2001 From: adam radford Date: Wed, 21 Sep 2005 17:20:14 -0700 Subject: [SCSI] 3ware 9000: Add support for 9550SX controllers Signed-off-by: Adam Radford Signed-off-by: James Bottomley diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index a6ac616..a748fbf 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -60,6 +60,7 @@ Remove un-needed eh_abort handler. Add support for embedded firmware error strings. 2.26.02.003 - Correctly handle single sgl's with use_sg=1. + 2.26.02.004 - Add support for 9550SX controllers. */ #include @@ -82,7 +83,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.003" +#define TW_DRIVER_VERSION "2.26.02.004" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -892,11 +893,6 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); } - if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "SBUF Write Error: clearing"); - writel(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); - } - if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) { if (tw_dev->reset_print == 0) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Microcontroller Error: clearing"); @@ -930,6 +926,36 @@ out: return retval; } /* End twa_empty_response_queue() */ +/* This function will clear the pchip/response queue on 9550SX */ +static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) +{ + u32 status_reg_value, response_que_value; + int count = 0, retval = 1; + + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + + while (((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) && (count < TW_MAX_RESPONSE_DRAIN)) { + response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); + if ((response_que_value & TW_9550SX_DRAIN_COMPLETED) == TW_9550SX_DRAIN_COMPLETED) { + /* P-chip settle time */ + msleep(500); + retval = 0; + goto out; + } + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); + count++; + } + if (count == TW_MAX_RESPONSE_DRAIN) + goto out; + + retval = 0; + } else + retval = 0; +out: + return retval; +} /* End twa_empty_response_queue_large() */ + /* This function passes sense keys from firmware to scsi layer */ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_sense, int print_host) { @@ -1613,8 +1639,16 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset) int tries = 0, retval = 1, flashed = 0, do_soft_reset = soft_reset; while (tries < TW_MAX_RESET_TRIES) { - if (do_soft_reset) + if (do_soft_reset) { TW_SOFT_RESET(tw_dev); + /* Clear pchip/response queue on 9550SX */ + if (twa_empty_response_queue_large(tw_dev)) { + TW_PRINTK(tw_dev->host, TW_DRIVER, 0x36, "Response queue (large) empty failed during reset sequence"); + do_soft_reset = 1; + tries++; + continue; + } + } /* Make sure controller is in a good state */ if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) { @@ -2034,7 +2068,10 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id goto out_free_device_extension; } - mem_addr = pci_resource_start(pdev, 1); + if (pdev->device == PCI_DEVICE_ID_3WARE_9000) + mem_addr = pci_resource_start(pdev, 1); + else + mem_addr = pci_resource_start(pdev, 2); /* Save base address */ tw_dev->base_addr = ioremap(mem_addr, PAGE_SIZE); @@ -2148,6 +2185,8 @@ static void twa_remove(struct pci_dev *pdev) static struct pci_device_id twa_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { } }; MODULE_DEVICE_TABLE(pci, twa_pci_tbl); diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 8c8ecbe..46f22cd 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -267,7 +267,6 @@ static twa_message_type twa_error_table[] = { #define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 #define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000 #define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 -#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008 /* Status register bit definitions */ #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 @@ -285,9 +284,8 @@ static twa_message_type twa_error_table[] = { #define TW_STATUS_MICROCONTROLLER_READY 0x00002000 #define TW_STATUS_COMMAND_QUEUE_EMPTY 0x00001000 #define TW_STATUS_EXPECTED_BITS 0x00002000 -#define TW_STATUS_UNEXPECTED_BITS 0x00F00008 -#define TW_STATUS_SBUF_WRITE_ERROR 0x00000008 -#define TW_STATUS_VALID_INTERRUPT 0x00DF0008 +#define TW_STATUS_UNEXPECTED_BITS 0x00F00000 +#define TW_STATUS_VALID_INTERRUPT 0x00DF0000 /* RESPONSE QUEUE BIT DEFINITIONS */ #define TW_RESPONSE_ID_MASK 0x00000FF0 @@ -324,9 +322,9 @@ static twa_message_type twa_error_table[] = { /* Compatibility defines */ #define TW_9000_ARCH_ID 0x5 -#define TW_CURRENT_DRIVER_SRL 28 -#define TW_CURRENT_DRIVER_BUILD 9 -#define TW_CURRENT_DRIVER_BRANCH 4 +#define TW_CURRENT_DRIVER_SRL 30 +#define TW_CURRENT_DRIVER_BUILD 80 +#define TW_CURRENT_DRIVER_BRANCH 0 /* Phase defines */ #define TW_PHASE_INITIAL 0 @@ -334,6 +332,7 @@ static twa_message_type twa_error_table[] = { #define TW_PHASE_SGLIST 2 /* Misc defines */ +#define TW_9550SX_DRAIN_COMPLETED 0xFFFF #define TW_SECTOR_SIZE 512 #define TW_ALIGNMENT_9000 4 /* 4 bytes */ #define TW_ALIGNMENT_9000_SGL 0x3 @@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = { #ifndef PCI_DEVICE_ID_3WARE_9000 #define PCI_DEVICE_ID_3WARE_9000 0x1002 #endif +#ifndef PCI_DEVICE_ID_3WARE_9550SX +#define PCI_DEVICE_ID_3WARE_9550SX 0x1003 +#endif /* Bitmask macros to eliminate bitfields */ @@ -443,6 +445,7 @@ static twa_message_type twa_error_table[] = { #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) #define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8)) #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) +#define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30) #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x))) #define TW_CLEAR_HOST_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_HOST_INTERRUPT, TW_CONTROL_REG_ADDR(x))) -- cgit v0.10.2 From 6f3a20242db2597312c50abc11f1e747c5d2326a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 22 Sep 2005 20:33:28 -0500 Subject: [SCSI] allow REPORT LUN scanning even for LUN 0 PQ of 3 Currently we just ignore the device, which means there are a few arrays out there that we don't find. This patch updates the scsi_report_lun_scan() to take a target instead of a device so it can be called on a return of SCSI_SCAN_TARGET_PRESENT, which is what a PQ 3 device returns. Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index fcf9f6c..327c5d7 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -587,6 +587,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, if (sdev->scsi_level >= 2 || (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) sdev->scsi_level++; + sdev->sdev_target->scsi_level = sdev->scsi_level; return 0; } @@ -771,6 +772,15 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) return SCSI_SCAN_LUN_PRESENT; } +static inline void scsi_destroy_sdev(struct scsi_device *sdev) +{ + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + transport_destroy_device(&sdev->sdev_gendev); + put_device(&sdev->sdev_gendev); +} + + /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it * @starget: pointer to target device structure @@ -803,9 +813,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * The rescan flag is used as an optimization, the first scan of a * host adapter calls into here with rescan == 0. */ - if (rescan) { - sdev = scsi_device_lookup_by_target(starget, lun); - if (sdev) { + sdev = scsi_device_lookup_by_target(starget, lun); + if (sdev) { + if (rescan || sdev->sdev_state != SDEV_CREATED) { SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: device exists on %s\n", sdev->sdev_gendev.bus_id)); @@ -820,9 +830,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev->model); return SCSI_SCAN_LUN_PRESENT; } - } - - sdev = scsi_alloc_sdev(starget, lun, hostdata); + scsi_device_put(sdev); + } else + sdev = scsi_alloc_sdev(starget, lun, hostdata); if (!sdev) goto out; @@ -877,12 +887,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, res = SCSI_SCAN_NO_RESPONSE; } } - } else { - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); - transport_destroy_device(&sdev->sdev_gendev); - put_device(&sdev->sdev_gendev); - } + } else + scsi_destroy_sdev(sdev); out: return res; } @@ -1054,7 +1060,7 @@ EXPORT_SYMBOL(int_to_scsilun); * 0: scan completed (or no memory, so further scanning is futile) * 1: no report lun scan, or not configured **/ -static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, +static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, int rescan) { char devname[64]; @@ -1067,7 +1073,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, struct scsi_lun *lunp, *lun_data; u8 *data; struct scsi_sense_hdr sshdr; - struct scsi_target *starget = scsi_target(sdev); + struct scsi_device *sdev; + struct Scsi_Host *shost = dev_to_shost(&starget->dev); /* * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. @@ -1075,15 +1082,23 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, * support more than 8 LUNs. */ if ((bflags & BLIST_NOREPORTLUN) || - sdev->scsi_level < SCSI_2 || - (sdev->scsi_level < SCSI_3 && - (!(bflags & BLIST_REPORTLUN2) || sdev->host->max_lun <= 8)) ) + starget->scsi_level < SCSI_2 || + (starget->scsi_level < SCSI_3 && + (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) ) return 1; if (bflags & BLIST_NOLUN) return 0; + if (!(sdev = scsi_device_lookup_by_target(starget, 0))) { + sdev = scsi_alloc_sdev(starget, 0, NULL); + if (!sdev) + return 0; + if (scsi_device_get(sdev)) + return 0; + } + sprintf(devname, "host %d channel %d id %d", - sdev->host->host_no, sdev->channel, sdev->id); + shost->host_no, sdev->channel, sdev->id); /* * Allocate enough to hold the header (the same size as one scsi_lun) @@ -1098,8 +1113,10 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, length = (max_scsi_report_luns + 1) * sizeof(struct scsi_lun); lun_data = kmalloc(length, GFP_ATOMIC | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); - if (!lun_data) + if (!lun_data) { + printk(ALLOC_FAILURE_MSG, __FUNCTION__); goto out; + } scsi_cmd[0] = REPORT_LUNS; @@ -1201,10 +1218,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, for (i = 0; i < sizeof(struct scsi_lun); i++) printk("%02x", data[i]); printk(" has a LUN larger than currently supported.\n"); - } else if (lun == 0) { - /* - * LUN 0 has already been scanned. - */ } else if (lun > sdev->host->max_lun) { printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" " than allowed by the host adapter\n", @@ -1227,13 +1240,13 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, } kfree(lun_data); - return 0; - out: - /* - * We are out of memory, don't try scanning any further. - */ - printk(ALLOC_FAILURE_MSG, __FUNCTION__); + scsi_device_put(sdev); + if (sdev->sdev_state == SDEV_CREATED) + /* + * the sdev we used didn't appear in the report luns scan + */ + scsi_destroy_sdev(sdev); return 0; } @@ -1299,7 +1312,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; int res; - struct scsi_device *sdev = NULL; struct scsi_target *starget; if (shost->this_id == id) @@ -1325,27 +1337,16 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * Scan LUN 0, if there is some response, scan further. Ideally, we * would not configure LUN 0 until all LUNs are scanned. */ - res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, NULL); - if (res == SCSI_SCAN_LUN_PRESENT) { - if (scsi_report_lun_scan(sdev, bflags, rescan) != 0) + res = scsi_probe_and_add_lun(starget, 0, &bflags, NULL, rescan, NULL); + if (res == SCSI_SCAN_LUN_PRESENT || res == SCSI_SCAN_TARGET_PRESENT) { + if (scsi_report_lun_scan(starget, bflags, rescan) != 0) /* * The REPORT LUN did not scan the target, * do a sequential scan. */ scsi_sequential_lun_scan(starget, bflags, - res, sdev->scsi_level, rescan); - } else if (res == SCSI_SCAN_TARGET_PRESENT) { - /* - * There's a target here, but lun 0 is offline so we - * can't use the report_lun scan. Fall back to a - * sequential lun scan with a bflags of SPARSELUN and - * a default scsi level of SCSI_2 - */ - scsi_sequential_lun_scan(starget, BLIST_SPARSELUN, - SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan); + res, starget->scsi_level, rescan); } - if (sdev) - scsi_device_put(sdev); out_reap: /* now determine if the target has any children at all @@ -1542,10 +1543,7 @@ void scsi_free_host_dev(struct scsi_device *sdev) { BUG_ON(sdev->id != sdev->host->this_id); - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); - transport_destroy_device(&sdev->sdev_gendev); - put_device(&sdev->sdev_gendev); + scsi_destroy_sdev(sdev); } EXPORT_SYMBOL(scsi_free_host_dev); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index c0e4c67..7ece056 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -163,6 +163,7 @@ struct scsi_target { unsigned int id; /* target id ... replace * scsi_device.id eventually */ unsigned long create:1; /* signal that it needs to be added */ + char scsi_level; void *hostdata; /* available to low-level driver */ unsigned long starget_data[0]; /* for the transport */ /* starget_data must be the last element!!!! */ -- cgit v0.10.2 From 44550322cb601ac3f882e7438bbeec971fa1b1a3 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 20 Sep 2005 13:32:11 -0700 Subject: [SCSI] qla2xxx: fix remote port timeout with qla2xxx driver This patch fixes a hole in the rport unblock handling when processing fabric events via the ADISC/PLOGI device state machine. Original code would not properly 'unblock' the port upon the port reloging into the fabric. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c index bdc3bc7..1eba988 100644 --- a/drivers/scsi/qla2xxx/qla_rscn.c +++ b/drivers/scsi/qla2xxx/qla_rscn.c @@ -330,6 +330,8 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat, fcport->flags &= ~FCF_FAILOVER_NEEDED; fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_ONLINE); + if (fcport->rport) + fc_remote_port_unblock(fcport->rport); } -- cgit v0.10.2 From f04da5def8c460b1b52d3142da827ab01efa3a15 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 25 Sep 2005 23:02:49 +0100 Subject: [ARM] 2933/1: S3C2410 - fix serial port warnings Patch from Ben Dooks Fix the following warnings produced from drivers/char/s3c2410.c. drivers/serial/s3c2410.c:757: warning: 'clk' may be used uninitialized drivers/serial/s3c2410.c:756: warning: 'clksrc' may be used uninitialized Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index c361c6f..1195e6a 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -753,8 +753,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); - struct s3c24xx_uart_clksrc *clksrc; - struct clk *clk; + struct s3c24xx_uart_clksrc *clksrc = NULL; + struct clk *clk = NULL; unsigned long flags; unsigned int baud, quot; unsigned int ulcon; -- cgit v0.10.2 From 5b58745203f16ab83e50f4a015eea84c416d9279 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 25 Sep 2005 23:04:48 +0100 Subject: [ARM] 2934/1: Anubis - fix VA offsets for CPLD registers Patch from Ben Dooks The VA addresses of the Anubis CPLD registers confoict with the addresses for the ISA space maps used by the rest of the s3c2410 architecture Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h index 97741d6..d529ffd 100644 --- a/include/asm-arm/arch-s3c2410/anubis-map.h +++ b/include/asm-arm/arch-s3c2410/anubis-map.h @@ -20,22 +20,22 @@ /* start peripherals off after the S3C2410 */ -#define ANUBIS_IOADDR(x) (S3C2410_ADDR((x) + 0x02000000)) +#define ANUBIS_IOADDR(x) (S3C2410_ADDR((x) + 0x01800000)) #define ANUBIS_PA_CPLD (S3C2410_CS1 | (1<<26)) /* we put the CPLD registers next, to get them out of the way */ -#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) /* 0x01300000 */ +#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) /* 0x01800000 */ #define ANUBIS_PA_CTRL1 (ANUBIS_PA_CPLD) -#define ANUBIS_VA_CTRL2 ANUBIS_IOADDR(0x00100000) /* 0x01400000 */ +#define ANUBIS_VA_CTRL2 ANUBIS_IOADDR(0x00100000) /* 0x01900000 */ #define ANUBIS_PA_CTRL2 (ANUBIS_PA_CPLD) -#define ANUBIS_VA_CTRL3 ANUBIS_IOADDR(0x00200000) /* 0x01500000 */ +#define ANUBIS_VA_CTRL3 ANUBIS_IOADDR(0x00200000) /* 0x01A00000 */ #define ANUBIS_PA_CTRL3 (ANUBIS_PA_CPLD) -#define ANUBIS_VA_CTRL4 ANUBIS_IOADDR(0x00300000) /* 0x01600000 */ +#define ANUBIS_VA_CTRL4 ANUBIS_IOADDR(0x00300000) /* 0x01B00000 */ #define ANUBIS_PA_CTRL4 (ANUBIS_PA_CPLD) #define ANUBIS_IDEPRI ANUBIS_IOADDR(0x01000000) -- cgit v0.10.2 From fe8b2304e54552cea113318e2f66c45628130fdc Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 25 Sep 2005 23:10:33 +0200 Subject: [SCSI] sas: fix remote phy removal Brown paperbag bug: sas_rphy_delete was ordered completely wrong. Fix it up to be the same order as sas_phy_delete or fc_rport_terminate and fix rphy objects that leaked after module removal. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index ff724bbe..1d145d2 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -628,17 +628,16 @@ sas_rphy_delete(struct sas_rphy *rphy) struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); - transport_destroy_device(&rphy->dev); + scsi_remove_target(dev); - scsi_remove_target(&rphy->dev); + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); spin_lock(&sas_host->lock); list_del(&rphy->list); spin_unlock(&sas_host->lock); - transport_remove_device(dev); - device_del(dev); - transport_destroy_device(dev); put_device(&parent->dev); } EXPORT_SYMBOL(sas_rphy_delete); -- cgit v0.10.2 From 56425306517ef28a9b480161cdb96d182172bc1d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 25 Sep 2005 16:46:57 -0700 Subject: [SPARC64]: Add CONFIG_DEBUG_PAGEALLOC support. The trick is that we do the kernel linear mapping TLB miss starting with an instruction sequence like this: ba,pt %xcc, kvmap_load xor %g2, %g4, %g5 succeeded by an instruction sequence which performs a full page table walk starting at swapper_pg_dir. We first take over the trap table from the firmware. Then, using this constant PTE generation for the linear mapping area above, we build the kernel page tables for the linear mapping. After this is setup, we patch that branch above into a "nop", which will cause TLB misses to fall through to the full page table walk. With this, the page unmapping for CONFIG_DEBUG_PAGEALLOC is trivial. Signed-off-by: David S. Miller diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index af0e941..fa06ea0 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug @@ -33,6 +33,14 @@ config DEBUG_BOOTMEM depends on DEBUG_KERNEL bool "Debug BOOTMEM initialization" +config DEBUG_PAGEALLOC + bool "Page alloc debugging" + depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + config MCOUNT bool depends on STACK_DEBUG diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 56af714..ecc748f 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -525,12 +525,6 @@ bootup_user_stack_end: #include "ttable.S" #include "systbls.S" - - .align 1024 - .globl swapper_pg_dir -swapper_pg_dir: - .word 0 - #include "ktlb.S" #include "etrap.S" #include "rtrap.S" diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S index a591bc0..7796b37 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc64/kernel/ktlb.S @@ -132,9 +132,40 @@ kvmap_do_obp: */ .align 32 kvmap: - brlz,pt %g4, kvmap_load + brgez,pn %g4, kvmap_nonlinear + nop + +#ifdef CONFIG_DEBUG_PAGEALLOC + .globl kvmap_linear_patch +kvmap_linear_patch: +#endif + ba,pt %xcc, kvmap_load xor %g2, %g4, %g5 +#ifdef CONFIG_DEBUG_PAGEALLOC + sethi %hi(swapper_pg_dir), %g5 + or %g5, %lo(swapper_pg_dir), %g5 + sllx %g4, 64 - (PGDIR_SHIFT + PGDIR_BITS), %g6 + srlx %g6, 64 - PAGE_SHIFT, %g6 + andn %g6, 0x3, %g6 + lduw [%g5 + %g6], %g5 + brz,pn %g5, longpath + sllx %g4, 64 - (PMD_SHIFT + PMD_BITS), %g6 + srlx %g6, 64 - PAGE_SHIFT, %g6 + sllx %g5, 11, %g5 + andn %g6, 0x3, %g6 + lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brz,pn %g5, longpath + sllx %g4, 64 - PMD_SHIFT, %g6 + srlx %g6, 64 - PAGE_SHIFT, %g6 + sllx %g5, 11, %g5 + andn %g6, 0x7, %g6 + ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 + brz,pn %g5, longpath + nop + ba,a,pt %xcc, kvmap_load +#endif + kvmap_nonlinear: sethi %hi(MODULES_VADDR), %g5 cmp %g4, %g5 diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index f47d0be..2af0cf0 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S @@ -9,8 +9,7 @@ ENTRY(_start) jiffies = jiffies_64; SECTIONS { - swapper_pmd_dir = 0x0000000000402000; - empty_pg_dir = 0x0000000000403000; + swapper_low_pmd_dir = 0x0000000000402000; . = 0x4000; .text 0x0000000000404000 : { diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index cf747372..8d72f8a 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1332,15 +1332,114 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) return end_pfn; } +#ifdef CONFIG_DEBUG_PAGEALLOC +static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot) +{ + unsigned long vstart = PAGE_OFFSET + pstart; + unsigned long vend = PAGE_OFFSET + pend; + unsigned long alloc_bytes = 0UL; + + if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { + prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n", + vstart, vend); + prom_halt(); + } + + while (vstart < vend) { + unsigned long this_end, paddr = __pa(vstart); + pgd_t *pgd = pgd_offset_k(vstart); + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + pud = pud_offset(pgd, vstart); + if (pud_none(*pud)) { + pmd_t *new; + + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pud_populate(&init_mm, pud, new); + } + + pmd = pmd_offset(pud, vstart); + if (!pmd_present(*pmd)) { + pte_t *new; + + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pmd_populate_kernel(&init_mm, pmd, new); + } + + pte = pte_offset_kernel(pmd, vstart); + this_end = (vstart + PMD_SIZE) & PMD_MASK; + if (this_end > vend) + this_end = vend; + + while (vstart < this_end) { + pte_val(*pte) = (paddr | pgprot_val(prot)); + + vstart += PAGE_SIZE; + paddr += PAGE_SIZE; + pte++; + } + } + + return alloc_bytes; +} + +extern struct linux_mlist_p1275 *prom_ptot_ptr; +extern unsigned int kvmap_linear_patch[1]; + +static void __init kernel_physical_mapping_init(void) +{ + struct linux_mlist_p1275 *p = prom_ptot_ptr; + unsigned long mem_alloced = 0UL; + + while (p) { + unsigned long phys_start, phys_end; + + phys_start = p->start_adr; + phys_end = phys_start + p->num_bytes; + mem_alloced += kernel_map_range(phys_start, phys_end, + PAGE_KERNEL); + + p = p->theres_more; + } + + printk("Allocated %ld bytes for kernel page tables.\n", + mem_alloced); + + kvmap_linear_patch[0] = 0x01000000; /* nop */ + flushi(&kvmap_linear_patch[0]); + + __flush_tlb_all(); +} + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT; + unsigned long phys_end = phys_start + (numpages * PAGE_SIZE); + + kernel_map_range(phys_start, phys_end, + (enable ? PAGE_KERNEL : __pgprot(0))); + + /* we should perform an IPI and flush all tlbs, + * but that can deadlock->flush only current cpu. + */ + __flush_tlb_kernel_range(PAGE_OFFSET + phys_start, + PAGE_OFFSET + phys_end); +} +#endif + /* paging_init() sets up the page tables */ extern void cheetah_ecache_flush_init(void); static unsigned long last_valid_pfn; +pgd_t swapper_pg_dir[2048]; void __init paging_init(void) { - extern pmd_t swapper_pmd_dir[1024]; unsigned long end_pfn, pages_avail, shift; unsigned long real_end; @@ -1361,11 +1460,11 @@ void __init paging_init(void) */ init_mm.pgd += ((shift) / (sizeof(pgd_t))); - memset(swapper_pmd_dir, 0, sizeof(swapper_pmd_dir)); + memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); /* Now can init the kernel/bad page tables. */ pud_set(pud_offset(&swapper_pg_dir[0], 0), - swapper_pmd_dir + (shift / sizeof(pgd_t))); + swapper_low_pmd_dir + (shift / sizeof(pgd_t))); swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); @@ -1390,6 +1489,10 @@ void __init paging_init(void) pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail); +#ifdef CONFIG_DEBUG_PAGEALLOC + kernel_physical_mapping_init(); +#endif + { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h index ededd26..b3f6165 100644 --- a/include/asm-sparc64/cacheflush.h +++ b/include/asm-sparc64/cacheflush.h @@ -66,6 +66,11 @@ extern void flush_ptrace_access(struct vm_area_struct *, struct page *, #define flush_cache_vmap(start, end) do { } while (0) #define flush_cache_vunmap(start, end) do { } while (0) +#ifdef CONFIG_DEBUG_PAGEALLOC +/* internal debugging function */ +void kernel_map_pages(struct page *page, int numpages, int enable); +#endif + #endif /* !__ASSEMBLY__ */ #endif /* _SPARC64_CACHEFLUSH_H */ diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index a297f61..43cbb08 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -60,13 +60,13 @@ * table can map */ #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) -#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) #define PMD_BITS (PAGE_SHIFT - 2) /* PGDIR_SHIFT determines what a third-level page table entry can map */ #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) #define PGDIR_BITS (PAGE_SHIFT - 2) @@ -336,7 +336,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p #define pte_clear(mm,addr,ptep) \ set_pte_at((mm), (addr), (ptep), __pte(0UL)) -extern pgd_t swapper_pg_dir[1]; +extern pgd_t swapper_pg_dir[2048]; +extern pmd_t swapper_low_pmd_dir[2048]; /* These do nothing with the way I have things setup. */ #define mmu_lockarea(vaddr, len) (vaddr) -- cgit v0.10.2 From 80dc0d6b44ce0f01df58d8899e46612690ed7d81 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 26 Sep 2005 00:32:17 -0700 Subject: [SPARC64]: Probe D/I/E-cache config and use. At boot time, determine the D-cache, I-cache and E-cache size and line-size. Use them in cache flushes when appropriate. This change was motivated by discovering that the D-cache on UltraSparc-IIIi and later are 64K not 32K, and the flushes done by the Cheetah error handlers were assuming a 32K size. There are still some pieces of code that are hard coding things and will need to be fixed up at some point. While we're here, fix the D-cache and I-cache parity error handlers to run with interrupts disabled, and when the trap occurs at trap level > 1 log the event via a counter displayed in /proc/cpuinfo. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index d710274..df9a1ca 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -135,6 +135,28 @@ void __init device_scan(void) cpu_data(0).clock_tick = prom_getintdefault(cpu_node, "clock-frequency", 0); + cpu_data(0).dcache_size = prom_getintdefault(cpu_node, + "dcache-size", + 16 * 1024); + cpu_data(0).dcache_line_size = + prom_getintdefault(cpu_node, "dcache-line-size", 32); + cpu_data(0).icache_size = prom_getintdefault(cpu_node, + "icache-size", + 16 * 1024); + cpu_data(0).icache_line_size = + prom_getintdefault(cpu_node, "icache-line-size", 32); + cpu_data(0).ecache_size = prom_getintdefault(cpu_node, + "ecache-size", + 4 * 1024 * 1024); + cpu_data(0).ecache_line_size = + prom_getintdefault(cpu_node, "ecache-line-size", 64); + printk("CPU[0]: Caches " + "D[sz(%d):line_sz(%d)] " + "I[sz(%d):line_sz(%d)] " + "E[sz(%d):line_sz(%d)]\n", + cpu_data(0).dcache_size, cpu_data(0).dcache_line_size, + cpu_data(0).icache_size, cpu_data(0).icache_line_size, + cpu_data(0).ecache_size, cpu_data(0).ecache_line_size); } #endif diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 45cd3bb..2879b10 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -372,14 +372,13 @@ cheetah_plus_patch_fpdis: * * DATA 0: [low 32-bits] Address of function to call, jmp to this * [high 32-bits] MMU Context Argument 0, place in %g5 - * DATA 1: Address Argument 1, place in %g6 + * DATA 1: Address Argument 1, place in %g1 * DATA 2: Address Argument 2, place in %g7 * * With this method we can do most of the cross-call tlb/cache * flushing very quickly. * - * Current CPU's IRQ worklist table is locked into %g1, - * don't touch. + * Current CPU's IRQ worklist table is locked into %g6, don't touch. */ .text .align 32 @@ -853,13 +852,14 @@ cheetah_plus_dcpe_trap_vector: nop do_cheetah_plus_data_parity: - ba,pt %xcc, etrap + rdpr %pil, %g2 + wrpr %g0, 15, %pil + ba,pt %xcc, etrap_irq rd %pc, %g7 mov 0x0, %o0 call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 - ba,pt %xcc, rtrap - clr %l6 + ba,a,pt %xcc, rtrap_irq cheetah_plus_dcpe_trap_vector_tl1: membar #Sync @@ -883,13 +883,14 @@ cheetah_plus_icpe_trap_vector: nop do_cheetah_plus_insn_parity: - ba,pt %xcc, etrap + rdpr %pil, %g2 + wrpr %g0, 15, %pil + ba,pt %xcc, etrap_irq rd %pc, %g7 mov 0x1, %o0 call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 - ba,pt %xcc, rtrap - clr %l6 + ba,a,pt %xcc, rtrap_irq cheetah_plus_icpe_trap_vector_tl1: membar #Sync @@ -922,6 +923,10 @@ do_dcpe_tl1: nop wrpr %g1, %tl ! Restore original trap level do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + sethi %hi(dcache_parity_tl1_occurred), %g2 + lduw [%g2 + %lo(dcache_parity_tl1_occurred)], %g1 + add %g1, 1, %g1 + stw %g1, [%g2 + %lo(dcache_parity_tl1_occurred)] /* Reset D-cache parity */ sethi %hi(1 << 16), %g1 ! D-cache size mov (1 << 5), %g2 ! D-cache line size @@ -968,6 +973,10 @@ do_icpe_tl1: nop wrpr %g1, %tl ! Restore original trap level do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */ + sethi %hi(icache_parity_tl1_occurred), %g2 + lduw [%g2 + %lo(icache_parity_tl1_occurred)], %g1 + add %g1, 1, %g1 + stw %g1, [%g2 + %lo(icache_parity_tl1_occurred)] /* Flush I-cache */ sethi %hi(1 << 15), %g1 ! I-cache size mov (1 << 5), %g2 ! I-cache line size diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index f4345d8..8e8baf2 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -605,6 +605,9 @@ extern void smp_info(struct seq_file *); extern void smp_bogo(struct seq_file *); extern void mmu_info(struct seq_file *); +unsigned int dcache_parity_tl1_occurred; +unsigned int icache_parity_tl1_occurred; + static int show_cpuinfo(struct seq_file *m, void *__unused) { seq_printf(m, @@ -615,6 +618,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) "type\t\t: sun4u\n" "ncpus probed\t: %ld\n" "ncpus active\t: %ld\n" + "D$ parity tl1\t: %u\n" + "I$ parity tl1\t: %u\n" #ifndef CONFIG_SMP "Cpu0Bogo\t: %lu.%02lu\n" "Cpu0ClkTck\t: %016lx\n" @@ -627,7 +632,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) (prom_prev >> 8) & 0xff, prom_prev & 0xff, (long)num_possible_cpus(), - (long)num_online_cpus() + (long)num_online_cpus(), + dcache_parity_tl1_occurred, + icache_parity_tl1_occurred #ifndef CONFIG_SMP , cpu_data(0).udelay_val/(500000/HZ), (cpu_data(0).udelay_val/(5000/HZ)) % 100, diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index b4fc6a5..590df5a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id) cpu_data(id).pte_cache[1] = NULL; cpu_data(id).pgd_cache = NULL; cpu_data(id).idle_volume = 1; + + cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size", + 16 * 1024); + cpu_data(id).dcache_line_size = + prom_getintdefault(cpu_node, "dcache-line-size", 32); + cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size", + 16 * 1024); + cpu_data(id).icache_line_size = + prom_getintdefault(cpu_node, "icache-line-size", 32); + cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size", + 4 * 1024 * 1024); + cpu_data(id).ecache_line_size = + prom_getintdefault(cpu_node, "ecache-line-size", 64); + printk("CPU[%d]: Caches " + "D[sz(%d):line_sz(%d)] " + "I[sz(%d):line_sz(%d)] " + "E[sz(%d):line_sz(%d)]\n", + id, + cpu_data(id).dcache_size, cpu_data(id).dcache_line_size, + cpu_data(id).icache_size, cpu_data(id).icache_line_size, + cpu_data(id).ecache_size, cpu_data(id).ecache_line_size); } static void smp_setup_percpu_timer(void); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index b280b2e..f8e7005 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -869,14 +869,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr) */ static void __cheetah_flush_icache(void) { - unsigned long i; + unsigned int icache_size, icache_line_size; + unsigned long addr; + + icache_size = local_cpu_data().icache_size; + icache_line_size = local_cpu_data().icache_line_size; /* Clear the valid bits in all the tags. */ - for (i = 0; i < (1 << 15); i += (1 << 5)) { + for (addr = 0; addr < icache_size; addr += icache_line_size) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); + : "r" (addr | (2 << 3)), + "i" (ASI_IC_TAG)); } } @@ -904,13 +909,17 @@ static void cheetah_flush_icache(void) static void cheetah_flush_dcache(void) { - unsigned long i; + unsigned int dcache_size, dcache_line_size; + unsigned long addr; + + dcache_size = local_cpu_data().dcache_size; + dcache_line_size = local_cpu_data().dcache_line_size; - for (i = 0; i < (1 << 16); i += (1 << 5)) { + for (addr = 0; addr < dcache_size; addr += dcache_line_size) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (i), "i" (ASI_DCACHE_TAG)); + : "r" (addr), "i" (ASI_DCACHE_TAG)); } } @@ -921,24 +930,29 @@ static void cheetah_flush_dcache(void) */ static void cheetah_plus_zap_dcache_parity(void) { - unsigned long i; + unsigned int dcache_size, dcache_line_size; + unsigned long addr; + + dcache_size = local_cpu_data().dcache_size; + dcache_line_size = local_cpu_data().dcache_line_size; - for (i = 0; i < (1 << 16); i += (1 << 5)) { - unsigned long tag = (i >> 14); - unsigned long j; + for (addr = 0; addr < dcache_size; addr += dcache_line_size) { + unsigned long tag = (addr >> 14); + unsigned long line; __asm__ __volatile__("membar #Sync\n\t" "stxa %0, [%1] %2\n\t" "membar #Sync" : /* no outputs */ - : "r" (tag), "r" (i), + : "r" (tag), "r" (addr), "i" (ASI_DCACHE_UTAG)); - for (j = i; j < i + (1 << 5); j += (1 << 3)) + for (line = addr; line < addr + dcache_line_size; line += 8) __asm__ __volatile__("membar #Sync\n\t" "stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ - : "r" (j), "i" (ASI_DCACHE_DATA)); + : "r" (line), + "i" (ASI_DCACHE_DATA)); } } diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index 9a3a81f..74de79d 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -22,6 +22,16 @@ typedef struct { unsigned int __pad1; unsigned long *pte_cache[2]; unsigned long *pgd_cache; + + /* Dcache line 3, rarely used */ + unsigned int dcache_size; + unsigned int dcache_line_size; + unsigned int icache_size; + unsigned int icache_line_size; + unsigned int ecache_size; + unsigned int ecache_line_size; + unsigned int __pad2; + unsigned int __pad3; } cpuinfo_sparc; DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data); -- cgit v0.10.2 From 838bf9675a3d1ede01408aa105357b9ab43faf1b Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 26 Sep 2005 10:45:46 +0100 Subject: NTFS: Fix the definition of the CHKD ntfs record magic. It had an off by two error causing it to be CHKB instead of CHKD. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index dbf5c2a..d5491de 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -123,7 +123,7 @@ enum { magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ - magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */ + magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ /* Found in all ntfs record containing records. */ magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector -- cgit v0.10.2 From 5a8c0cc32bb6e029cd9c36f655c6b0955b0d9967 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 26 Sep 2005 10:48:54 +0100 Subject: NTFS: More $LogFile handling fixes: when chkdsk has been run, it can leave the restart pages in the journal without multi sector transfer protection fixups (i.e. the update sequence array is empty and in fact does not exist). Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 574896f..83f3322 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -22,14 +22,6 @@ ToDo/Notes: - Enable the code for setting the NT4 compatibility flag when we start making NTFS 1.2 specific modifications. -2.1.25-WIP - - - Fix sparse warnings that have crept in over time. - - Change ntfs_cluster_free() to require a write locked runlist on entry - since we otherwise get into a lock reversal deadlock if a read locked - runlist is passed in. In the process also change it to take an ntfs - inode instead of a vfs inode as parameter. - 2.1.24 - Lots of bug fixes and support more clean journal states. - Support journals ($LogFile) which have been modified by chkdsk. This @@ -37,7 +29,8 @@ ToDo/Notes: The Windows boot will run chkdsk and then reboot. The user can then immediately boot into Linux rather than having to do a full Windows boot first before rebooting into Linux and we will recognize such a - journal and empty it as it is clean by definition. + journal and empty it as it is clean by definition. Note, this only + works if chkdsk left the journal in an obviously clean state. - Support journals ($LogFile) with only one restart page as well as journals with two different restart pages. We sanity check both and either use the only sane one or the more recent one of the two in the @@ -102,6 +95,13 @@ ToDo/Notes: my ways. - Fix various bugs in the runlist merging code. (Based on libntfs changes by Richard Russon.) + - Fix sparse warnings that have crept in over time. + - Change ntfs_cluster_free() to require a write locked runlist on entry + since we otherwise get into a lock reversal deadlock if a read locked + runlist is passed in. In the process also change it to take an ntfs + inode instead of a vfs inode as parameter. + - Fix the definition of the CHKD ntfs record magic. It had an off by + two error causing it to be CHKB instead of CHKD. 2.1.23 - Implement extension of resident files and make writing safe as well as many bug fixes, cleanups, and enhancements... diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index a3ce2c0..894b2b8 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.25-WIP\" +EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.24\" ifeq ($(CONFIG_NTFS_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 0173e95..0fd7029 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c @@ -51,7 +51,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, RESTART_PAGE_HEADER *rp, s64 pos) { u32 logfile_system_page_size, logfile_log_page_size; - u16 usa_count, usa_ofs, usa_end, ra_ofs; + u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; + BOOL have_usa = TRUE; ntfs_debug("Entering."); /* @@ -86,6 +87,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, (int)sle16_to_cpu(rp->minor_ver)); return FALSE; } + /* + * If chkdsk has been run the restart page may not be protected by an + * update sequence array. + */ + if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { + have_usa = FALSE; + goto skip_usa_checks; + } /* Verify the size of the update sequence array. */ usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); if (usa_count != le16_to_cpu(rp->usa_count)) { @@ -102,6 +111,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, "inconsistent update sequence array offset."); return FALSE; } +skip_usa_checks: /* * Verify the position of the restart area. It must be: * - aligned to 8-byte boundary, @@ -109,7 +119,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, * - within the system page size. */ ra_ofs = le16_to_cpu(rp->restart_area_offset); - if (ra_ofs & 7 || ra_ofs < usa_end || + if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : + ra_ofs < sizeof(RESTART_PAGE_HEADER)) || ra_ofs > logfile_system_page_size) { ntfs_error(vi->i_sb, "$LogFile restart page specifies " "inconsistent restart area offset."); @@ -402,8 +413,12 @@ static int ntfs_check_and_load_restart_page(struct inode *vi, idx++; } while (to_read > 0); } - /* Perform the multi sector transfer deprotection on the buffer. */ - if (post_read_mst_fixup((NTFS_RECORD*)trp, + /* + * Perform the multi sector transfer deprotection on the buffer if the + * restart page is protected. + */ + if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) + && post_read_mst_fixup((NTFS_RECORD*)trp, le32_to_cpu(rp->system_page_size))) { /* * A multi sector tranfer error was detected. We only need to @@ -615,11 +630,16 @@ is_empty: * Otherwise just throw it away. */ if (rstr2_lsn > rstr1_lsn) { + ntfs_debug("Using second restart page as it is more " + "recent."); ntfs_free(rstr1_ph); rstr1_ph = rstr2_ph; /* rstr1_lsn = rstr2_lsn; */ - } else + } else { + ntfs_debug("Using first restart page as it is more " + "recent."); ntfs_free(rstr2_ph); + } rstr2_ph = NULL; } /* All consistency checks passed. */ -- cgit v0.10.2 From 8c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Sun, 21 Aug 2005 22:29:26 -0700 Subject: [PATCH] yenta: auto-tune EnE bridges for CardBus cards Echo Audio cardbus products are known to be incompatible with EnE bridges. in order to maybe solve the problem a EnE specific test bit has to be set, another cleared...but other setups have a good chance to break when just forcing the bits. so do the whole thingy automatically. The patch adds a hook in cb_alloc() that allows special tuning for the different chipsets. for ene just match the Echo products and set/clear the test bits, defaults to do the same thing as w/o the patch to not break working setups. Signed-off-by: Daniel Ritz Cc: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 1d755e2..3f6d51d 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); cardbus_assign_irqs(bus, s->pci_irq); + + /* socket specific tune function */ + if (s->tune_bridge) + s->tune_bridge(s, bus); + pci_enable_bridges(bus); pci_bus_add_devices(bus); diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index fbe233e..d319f2e 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -153,6 +153,12 @@ /* EnE test register */ #define ENE_TEST_C9 0xc9 /* 8bit */ #define ENE_TEST_C9_TLTENABLE 0x02 +#define ENE_TEST_C9_PFENABLE_F0 0x04 +#define ENE_TEST_C9_PFENABLE_F1 0x08 +#define ENE_TEST_C9_PFENABLE (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0) +#define ENE_TEST_C9_WPDISALBLE_F0 0x40 +#define ENE_TEST_C9_WPDISALBLE_F1 0x80 +#define ENE_TEST_C9_WPDISALBLE (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1) /* * Texas Instruments CardBus controller overrides. @@ -791,16 +797,6 @@ static int ti12xx_override(struct yenta_socket *socket) config_writel(socket, TI113X_SYSTEM_CONTROL, val); /* - * for EnE bridges only: clear testbit TLTEnable. this makes the - * RME Hammerfall DSP sound card working. - */ - if (socket->dev->vendor == PCI_VENDOR_ID_ENE) { - u8 test_c9 = config_readb(socket, ENE_TEST_C9); - test_c9 &= ~ENE_TEST_C9_TLTENABLE; - config_writeb(socket, ENE_TEST_C9, test_c9); - } - - /* * Yenta expects controllers to use CSCINT to route * CSC interrupts to PCI rather than INTVAL. */ @@ -841,5 +837,75 @@ static int ti1250_override(struct yenta_socket *socket) return ti12xx_override(socket); } + +/** + * EnE specific part. EnE bridges are register compatible with TI bridges but + * have their own test registers and more important their own little problems. + * Some fixup code to make everybody happy (TM). + */ + +/** + * set/clear various test bits: + * Defaults to clear the bit. + * - mask (u8) defines what bits to change + * - bits (u8) is the values to change them to + * -> it's + * current = (current & ~mask) | bits + */ +/* pci ids of devices that wants to have the bit set */ +#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) { \ + .vendor = _vend, \ + .device = _dev, \ + .subvendor = _subvend, \ + .subdevice = _subdev, \ + .driver_data = ((mask) << 8 | (bits)), \ + } +static struct pci_device_id ene_tune_tbl[] = { + /* Echo Audio products based on motorola DSP56301 and DSP56361 */ + DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID, + ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), + DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID, + ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), + + {} +}; + +static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + struct pci_dev *dev; + struct pci_device_id *id = NULL; + u8 test_c9, old_c9, mask, bits; + + list_for_each_entry(dev, &bus->devices, bus_list) { + id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev); + if (id) + break; + } + + test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9); + if (id) { + mask = (id->driver_data >> 8) & 0xFF; + bits = id->driver_data & 0xFF; + + test_c9 = (test_c9 & ~mask) | bits; + } + else + /* default to clear TLTEnable bit, old behaviour */ + test_c9 &= ~ENE_TEST_C9_TLTENABLE; + + printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9); + config_writeb(socket, ENE_TEST_C9, test_c9); +} + + +static int ene_override(struct yenta_socket *socket) +{ + /* install tune_bridge() function */ + socket->socket.tune_bridge = ene_tune_bridge; + + return ti1250_override(socket); +} + #endif /* _LINUX_TI113X_H */ diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index ba4d78e..fd2a6f8 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -819,6 +819,7 @@ enum { CARDBUS_TYPE_TOPIC95, CARDBUS_TYPE_TOPIC97, CARDBUS_TYPE_O2MICRO, + CARDBUS_TYPE_ENE, }; /* @@ -865,6 +866,12 @@ static struct cardbus_type cardbus_type[] = { .override = o2micro_override, .restore_state = o2micro_restore_state, }, + [CARDBUS_TYPE_ENE] = { + .override = ene_override, + .save_state = ti_save_state, + .restore_state = ti_restore_state, + .sock_init = ti_init, + }, }; @@ -1265,10 +1272,10 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b86a4b7..92efb2c 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2187,7 +2187,12 @@ #define PCI_DEVICE_ID_ENE_1211 0x1211 #define PCI_DEVICE_ID_ENE_1225 0x1225 #define PCI_DEVICE_ID_ENE_1410 0x1410 +#define PCI_DEVICE_ID_ENE_710 0x1411 +#define PCI_DEVICE_ID_ENE_712 0x1412 #define PCI_DEVICE_ID_ENE_1420 0x1420 +#define PCI_DEVICE_ID_ENE_720 0x1421 +#define PCI_DEVICE_ID_ENE_722 0x1422 + #define PCI_VENDOR_ID_CHELSIO 0x1425 #define PCI_VENDOR_ID_MIPS 0x153f diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 0f7aacc..c8592c7 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -21,6 +21,9 @@ #include #include #include +#ifdef CONFIG_CARDBUS +#include +#endif /* Definitions for card status flags for GetStatus */ #define SS_WRPROT 0x0001 @@ -233,7 +236,11 @@ struct pcmcia_socket { /* so is power hook */ int (*power_hook)(struct pcmcia_socket *sock, int operation); - +#ifdef CONFIG_CARDBUS + /* allows tuning the CB bridge before loading driver for the CB card */ + void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus); +#endif + /* state thread */ struct semaphore skt_sem; /* protects socket h/w state */ -- cgit v0.10.2 From a413c09094e4df714c274690928dcf8125daf7e8 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Wed, 24 Aug 2005 17:03:23 +0200 Subject: [PATCH] yenta: don't mess with bridge control register In interrupt probing (both ISA and PCI) the bridge control register is used to change interrupt routing to ISA or PCI by changing bit 7. But this bit only controls the routing of card functional interrupts, not the CSC interrupts which are used for interrupt probing. A bad side effect of messing with this register in yenta_probe_irq() is that it can lead to irq storms if a card is inserted and already powered by the BIOS. Usage in yenta_sock_init() and yenta_config_init() seem to be fishy as well. Signed-off-by: Daniel Ritz Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index fd2a6f8..53a02f0 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -559,12 +559,6 @@ static void yenta_interrogate(struct yenta_socket *socket) static int yenta_sock_init(struct pcmcia_socket *sock) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - u16 bridge; - - bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; - if (!socket->cb_irq) - bridge |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge); exca_writeb(socket, I365_GBLCTL, 0x00); exca_writeb(socket, I365_GENCTL, 0x00); @@ -890,16 +884,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas { int i; unsigned long val; - u16 bridge_ctrl; u32 mask; - /* Set up ISA irq routing to probe the ISA irqs.. */ - bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); - if (!(bridge_ctrl & CB_BRIDGE_INTR)) { - bridge_ctrl |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - } - /* * Probe for usable interrupts using the force * register to generate bogus card status events. @@ -921,9 +907,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas mask = probe_irq_mask(val) & 0xffff; - bridge_ctrl &= ~CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - return mask; } @@ -951,18 +934,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re /* probes the PCI interrupt, use only on override functions */ static int yenta_probe_cb_irq(struct yenta_socket *socket) { - u16 bridge_ctrl; - if (!socket->cb_irq) return -1; socket->probe_status = 0; - /* disable ISA interrupts */ - bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); - bridge_ctrl &= ~CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) { printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n"); return -1; @@ -973,7 +949,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); - + msleep(100); /* disable interrupts */ @@ -1038,8 +1014,8 @@ static void yenta_config_init(struct yenta_socket *socket) * - PCI interrupts enabled if a PCI interrupt exists.. */ bridge = config_readw(socket, CB_BRIDGE_CONTROL); - bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); - bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR; + bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); + bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; config_writew(socket, CB_BRIDGE_CONTROL, bridge); } -- cgit v0.10.2 From 8e5d17ebe41eb98a538ef13aad36da5136701aab Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 7 Sep 2005 16:00:28 -0700 Subject: [PATCH] yenta: tiny cleanup pci_set_power_state is not needed, as we call pci_enable_device() somewhere else. Also, the resource we write to PCI_BASE_ADDRESS_0 needs to be converted to bus-centric view first. Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 53a02f0..80806c9 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -987,11 +987,12 @@ static void yenta_config_init(struct yenta_socket *socket) { u16 bridge; struct pci_dev *dev = socket->dev; + struct pci_bus_region region; - pci_set_power_state(socket->dev, 0); + pcibios_resource_to_bus(socket->dev, ®ion, &dev->resource[0]); config_writel(socket, CB_LEGACY_MODE_BASE, 0); - config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start); + config_writel(socket, PCI_BASE_ADDRESS_0, region.start); config_writew(socket, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | -- cgit v0.10.2 From 81000808b636b75a0ff5ef86c28f24fc6f5151eb Mon Sep 17 00:00:00 2001 From: Komuro Date: Sat, 24 Sep 2005 23:12:40 -0700 Subject: [PATCH] pcmcia: fix Kconfig dependency TCIC depends on ISA. It is used with ISA-bus system only. Signed-off-by: komurojun-mbn@nifty.com Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index ddc741e..36cc9a9 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -146,7 +146,7 @@ config I82365 config TCIC tristate "Databook TCIC host bridge support" - depends on PCMCIA + depends on PCMCIA && ISA select PCCARD_NONSTATIC help Say Y here to include support for the Databook TCIC family of PCMCIA -- cgit v0.10.2 From 6c1a10dba92cbacb58563f5eacf93807125b488a Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Tue, 20 Sep 2005 14:12:17 -0700 Subject: [PATCH] yenta: add support for more TI bridges Support some more TI cardbus bridges. most of them are multifunction devices which adds 1394 controllers, smartcard readers etc. this could also help with the various problems with the XX21 controllers seen on the linux-pcmcia list. Signed-off-by: Daniel Ritz Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index d319f2e..da0b404 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -59,6 +59,7 @@ #define TI122X_SCR_SER_STEP 0xc0000000 #define TI122X_SCR_INTRTIE 0x20000000 +#define TIXX21_SCR_TIEALL 0x10000000 #define TI122X_SCR_CBRSVD 0x00400000 #define TI122X_SCR_MRBURSTDN 0x00008000 #define TI122X_SCR_MRBURSTUP 0x00004000 @@ -624,6 +625,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) int devfn; unsigned int state; int ret = 1; + u32 sysctl; /* catch the two-slot controllers */ switch (socket->dev->device) { @@ -646,6 +648,24 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) */ break; + case PCI_DEVICE_ID_TI_X515: + case PCI_DEVICE_ID_TI_X420: + case PCI_DEVICE_ID_TI_X620: + case PCI_DEVICE_ID_TI_XX21_XX11: + case PCI_DEVICE_ID_TI_7410: + case PCI_DEVICE_ID_TI_7610: + /* + * those are either single or dual slot CB with additional functions + * like 1394, smartcard reader, etc. check the TIEALL flag for them + * the TIEALL flag binds the IRQ of all functions toghether. + * we catch the single slot variants later. + */ + sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); + if (sysctl & TIXX21_SCR_TIEALL) + return 0; + + break; + /* single-slot controllers have the 2nd slot empty always :) */ default: return 1; @@ -658,6 +678,15 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) if (!func) return 1; + /* + * check that the device id of both slots match. this is needed for the + * XX21 and the XX11 controller that share the same device id for single + * and dual slot controllers. return '2nd slot empty'. we already checked + * if the interrupt is tied to another function. + */ + if (socket->dev->device != func->device) + goto out; + slot2 = pci_get_drvdata(func); if (!slot2) goto out; diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 80806c9..c3e22fc 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1249,6 +1249,14 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 92efb2c..68f11ac 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -769,6 +769,8 @@ #define PCI_DEVICE_ID_TI_TVP4010 0x3d04 #define PCI_DEVICE_ID_TI_TVP4020 0x3d07 #define PCI_DEVICE_ID_TI_4450 0x8011 +#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 +#define PCI_DEVICE_ID_TI_X515 0x8036 #define PCI_DEVICE_ID_TI_1130 0xac12 #define PCI_DEVICE_ID_TI_1031 0xac13 #define PCI_DEVICE_ID_TI_1131 0xac15 @@ -785,12 +787,17 @@ #define PCI_DEVICE_ID_TI_4451 0xac42 #define PCI_DEVICE_ID_TI_4510 0xac44 #define PCI_DEVICE_ID_TI_4520 0xac46 +#define PCI_DEVICE_ID_TI_7510 0xac47 +#define PCI_DEVICE_ID_TI_7610 0xac48 +#define PCI_DEVICE_ID_TI_7410 0xac49 #define PCI_DEVICE_ID_TI_1410 0xac50 #define PCI_DEVICE_ID_TI_1420 0xac51 #define PCI_DEVICE_ID_TI_1451A 0xac52 #define PCI_DEVICE_ID_TI_1620 0xac54 #define PCI_DEVICE_ID_TI_1520 0xac55 #define PCI_DEVICE_ID_TI_1510 0xac56 +#define PCI_DEVICE_ID_TI_X620 0xac8d +#define PCI_DEVICE_ID_TI_X420 0xac8e #define PCI_VENDOR_ID_SONY 0x104d #define PCI_DEVICE_ID_SONY_CXD3222 0x8039 -- cgit v0.10.2 From a42f0dc4376fc574980864f890d1527894719cde Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 24 Sep 2005 23:12:44 -0700 Subject: [PATCH] pcmcia: new IDs for serial_cs Add new ID to serial_cs.c; the CIS fimware override is available by the manufacturer at http://www.sierrawireless.com . Remember to name the CIS binary SW_7xx_SER.cis and to put it into /lib/firmware/ Signed-off-by: Dominik Brodowski diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 1ae0b38..2c7d3ef 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), -- cgit v0.10.2 From f9cb8b71e7d6c858b1afe665fd0a09169fdf4390 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Sat, 24 Sep 2005 23:12:46 -0700 Subject: [PATCH] yenta: more ENE bridges Adds better support for the CB-710, CB-712, CB-720 and CB-722 bridges from EnE Signed-off-by: Daniel Ritz Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index c3e22fc..db9f952 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1257,6 +1257,10 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), -- cgit v0.10.2 From 2570b746484cfddf4b7b4715dbb69d53d5284f4d Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sat, 17 Sep 2005 11:17:56 +0200 Subject: [PATCH] pcmcia: update ID for NinjaATA Christian Zoz reported there are multiple NinjaATA devices all sharing the second product ID string, but not the first one. Signed-off-by: Dominik Brodowski diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 0ccf85f..a35a58b 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -477,7 +477,7 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79), + PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), -- cgit v0.10.2 From 4fb7edce52e5b6cf41e3375822d74a27f0b6f2dd Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Sun, 25 Sep 2005 14:39:46 +0200 Subject: [PATCH] pcmcia: fix cross-platform issues with pcmcia module aliases - Added a missing TO_NATIVE call to scripts/mod/file2alias.c:do_pcmcia_entry() - Add an alignment attribute to struct pcmcia_device_no to solve an alignment issue seen when cross-compiling on x86 for m68k. Signed-off-by: Kars de Jong Signed-off-by: Dominik Brodowski diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 47da39b..4ed2107 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -209,10 +209,11 @@ struct pcmcia_device_id { /* for real multi-function devices */ __u8 function; - /* for pseude multi-function devices */ + /* for pseudo multi-function devices */ __u8 device_no; - __u32 prod_id_hash[4]; + __u32 prod_id_hash[4] + __attribute__((aligned(sizeof(__u32)))); /* not matched against in kernelspace*/ #ifdef __KERNEL__ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index d8ee38a..f2ee673 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -295,11 +295,13 @@ static int do_pcmcia_entry(const char *filename, { unsigned int i; + id->match_flags = TO_NATIVE(id->match_flags); id->manf_id = TO_NATIVE(id->manf_id); id->card_id = TO_NATIVE(id->card_id); id->func_id = TO_NATIVE(id->func_id); id->function = TO_NATIVE(id->function); id->device_no = TO_NATIVE(id->device_no); + for (i=0; i<4; i++) { id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]); } -- cgit v0.10.2 From cbf8fd9f5aa5164e05cb04d4a34fcbe82f60beeb Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 26 Sep 2005 15:30:20 +0100 Subject: [ARM] Remove SA_IRQNOMASK SA_IRQNOMASK is unused, remove it. Signed-off-by: Russell King diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h index 760f6e65..ced6916 100644 --- a/include/asm-arm/signal.h +++ b/include/asm-arm/signal.h @@ -115,7 +115,6 @@ typedef unsigned long sigset_t; #ifdef __KERNEL__ #define SA_TIMER 0x40000000 -#define SA_IRQNOMASK 0x08000000 #endif #include -- cgit v0.10.2 From e2fcc61ef0d654887b651bd99ffcb52f7344b836 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 26 Sep 2005 17:02:41 +0100 Subject: NTFS: Re-fix sparse warnings in a more correct way, i.e. don't use an enum with different types in it but #define the two constants instead. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index d5491de..01f2dfa 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -308,22 +308,19 @@ typedef le16 MFT_RECORD_FLAGS; * The _LE versions are to be applied on little endian MFT_REFs. * Note: The _LE versions will return a CPU endian formatted value! */ -typedef enum { - MFT_REF_MASK_CPU = 0x0000ffffffffffffULL, - MFT_REF_MASK_LE = const_cpu_to_le64(0x0000ffffffffffffULL), -} MFT_REF_CONSTS; +#define MFT_REF_MASK_CPU 0x0000ffffffffffffULL +#define MFT_REF_MASK_LE const_cpu_to_le64(0x0000ffffffffffffULL) typedef u64 MFT_REF; typedef le64 leMFT_REF; #define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \ - ((MFT_REF)(m) & (u64)MFT_REF_MASK_CPU))) + ((MFT_REF)(m) & MFT_REF_MASK_CPU))) #define MK_LE_MREF(m, s) cpu_to_le64(MK_MREF(m, s)) -#define MREF(x) ((unsigned long)((x) & (u64)MFT_REF_MASK_CPU)) +#define MREF(x) ((unsigned long)((x) & MFT_REF_MASK_CPU)) #define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff)) -#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & \ - (u64)MFT_REF_MASK_CPU)) +#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & MFT_REF_MASK_CPU)) #define MSEQNO_LE(x) ((u16)((le64_to_cpu(x) >> 48) & 0xffff)) #define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0) -- cgit v0.10.2 From 018771f435388f22f388eb8658c652086fb3633e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 21 Sep 2005 21:40:12 -0700 Subject: [IB] mthca: Fix doorbell record resource leak If we allocate a bunch of doorbell records and then free them, we'll end up with completely empty pages, which we then free. However, when we come back to allocate more doorbell pages, we have to reallocate those empty pages rather than always trying to take a slot that we've never used. If we don't, we eventually use up every slot and fail to allocate a doorbell record, even though we have plenty of free space. Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 1827400..d0c41fe 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) goto found; } + for (i = start; i != end; i += dir) + if (!dev->db_tab->page[i].db_rec) { + page = dev->db_tab->page + i; + goto alloc; + } + if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) { ret = -ENOMEM; goto out; } + if (group == 0) + ++dev->db_tab->max_group1; + else + --dev->db_tab->min_group2; + page = dev->db_tab->page + end; + +alloc: page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096, &page->mapping, GFP_KERNEL); if (!page->db_rec) { @@ -554,10 +567,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) } bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE); - if (group == 0) - ++dev->db_tab->max_group1; - else - --dev->db_tab->min_group2; found: j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE); -- cgit v0.10.2 From f7ed3a5971da98acdc506bdbdef25cfe51c334a2 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 26 Sep 2005 09:29:33 -0700 Subject: [IB] mthca: fix off by one in clr_int calculation We should use the first word of the clear interrupt register if the bit we're after is < 32, not < 31. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 78152a8..c81fa8e 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) dev->eq_table.clr_mask = swab32(1 << (dev->eq_table.inta_pin & 31)); dev->eq_table.clr_int = dev->clr_base + - (dev->eq_table.inta_pin < 31 ? 4 : 0); + (dev->eq_table.inta_pin < 32 ? 4 : 0); } dev->eq_table.arm_mask = 0; -- cgit v0.10.2 From 44dd823b00fa64bf01e53557d28555011f122a88 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 26 Sep 2005 09:42:09 -0700 Subject: [IB] mthca: Fix off by one bug in mthca_map_cmd The loop in mthca_map_cmd() would fill one entry past the end of the mailbox buffer before calling the firmware command. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index cc758a2..f6a8ac0 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, err = -EINVAL; goto out; } - for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) { + for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { if (virt != -1) { pages[nent * 2] = cpu_to_be64(virt); virt += 1 << lg; @@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, ts += 1 << (lg - 10); ++tc; - if (nent == MTHCA_MAILBOX_SIZE / 16) { + if (++nent == MTHCA_MAILBOX_SIZE / 16) { err = mthca_cmd(dev, mailbox->dma, nent, 0, op, CMD_TIME_CLASS_B, status); if (err || *status) -- cgit v0.10.2 From 6132f9e146150473f803323dc8064a5506e33952 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 26 Sep 2005 19:52:56 +0100 Subject: [ARM] 2935/1: ixp4xx: fix warnings in ixp4xx_set_irq_type Patch from David Vrabel Signed-off-by: David Vrabel Signed-off-by: Russell King diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 52ad113..36b6045 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -125,7 +125,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) } else if (type & IRQT_LOW) { int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; irq_type = IXP4XX_IRQ_LEVEL; - } + } else + return -EINVAL; ixp4xx_config_irq(irq, irq_type); @@ -142,6 +143,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) /* Set the new style */ *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); + + return 0; } static void ixp4xx_irq_mask(unsigned int irq) -- cgit v0.10.2 From 819ccc86a43739e0cf443b6d6641a8722869be01 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 26 Sep 2005 19:52:57 +0100 Subject: [ARM] 2936/1: ixp4xx default config fixes Patch from Vincent Sanders A recent patch which made IXP4xx mach_desc's depend on config options had the effect of not building the kernel for several machines it possibly could be, this patch updates the default config to ensure all possible machines are built for by default. Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index 94aafec..c279e41 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -1,14 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-rc1-bk2 -# Sun Mar 27 22:53:40 2005 +# Linux kernel version: 2.6.14-rc1-git5 +# Tue Sep 20 17:26:28 2005 # CONFIG_ARM=y CONFIG_MMU=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_IOMAP=y # # Code maturity level options @@ -16,11 +15,13 @@ CONFIG_GENERIC_IOMAP=y CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -31,10 +32,13 @@ CONFIG_SYSCTL=y # CONFIG_HOTPLUG is not set CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -81,6 +85,7 @@ CONFIG_ARCH_IXP4XX=y # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y # @@ -90,15 +95,16 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y # # IXP4xx Platforms # -# CONFIG_ARCH_AVILA is not set +CONFIG_ARCH_AVILA=y CONFIG_ARCH_ADI_COYOTE=y CONFIG_ARCH_IXDP425=y -# CONFIG_MACH_IXDPG425 is not set -# CONFIG_MACH_IXDP465 is not set +CONFIG_MACH_IXDPG425=y +CONFIG_MACH_IXDP465=y CONFIG_ARCH_IXCDP1100=y CONFIG_ARCH_PRPMC1100=y CONFIG_ARCH_IXDP4XX=y -# CONFIG_MACH_GTWX5715 is not set +CONFIG_CPU_IXP46X=y +CONFIG_MACH_GTWX5715=y # # IXP4xx Options @@ -114,7 +120,6 @@ CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5T=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_MINICACHE=y # # Processor Features @@ -127,9 +132,10 @@ CONFIG_DMABOUNCE=y # # Bus support # +CONFIG_ISA_DMA_API=y CONFIG_PCI=y CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y +# CONFIG_PCI_DEBUG is not set # # PCCARD (PCMCIA/CardBus) support @@ -140,6 +146,15 @@ CONFIG_PCI_NAMES=y # Kernel Features # # CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set CONFIG_ALIGNMENT_TRAP=y # @@ -175,6 +190,241 @@ CONFIG_PM=y CONFIG_APM=y # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +# CONFIG_IP_VS_PROTO_TCP is not set +# CONFIG_IP_VS_PROTO_UDP is not set +# CONFIG_IP_VS_PROTO_ESP is not set +# CONFIG_IP_VS_PROTO_AH is not set + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +# CONFIG_IP_VS_SED is not set +# CONFIG_IP_VS_NQ is not set + +# +# IPVS application helper +# +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +# CONFIG_IP_NF_TFTP is not set +# CONFIG_IP_NF_AMANDA is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +# CONFIG_IP_NF_MATCH_IPRANGE is not set +CONFIG_IP_NF_MATCH_MAC=m +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +# CONFIG_IP_NF_MATCH_RECENT is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_DSCP is not set +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +# CONFIG_IP_NF_MATCH_HELPER is not set +CONFIG_IP_NF_MATCH_STATE=m +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +CONFIG_IP_NF_MATCH_OWNER=m +# CONFIG_IP_NF_MATCH_PHYSDEV is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set +# CONFIG_IP_NF_MATCH_SCTP is not set +# CONFIG_IP_NF_MATCH_DCCP is not set +# CONFIG_IP_NF_MATCH_COMMENT is not set +# CONFIG_IP_NF_MATCH_HASHLIMIT is not set +# CONFIG_IP_NF_MATCH_STRING is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +CONFIG_IP_NF_TARGET_MARK=m +# CONFIG_IP_NF_TARGET_CLASSIFY is not set +# CONFIG_IP_NF_TARGET_TTL is not set +# CONFIG_IP_NF_RAW is not set +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +# CONFIG_IP_NF_ARP_MANGLE is not set + +# +# Bridge: Netfilter Configuration +# +# CONFIG_BRIDGE_NF_EBTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=y +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +# CONFIG_NET_DIVERT is not set +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +# CONFIG_NET_SCH_NETEM is not set +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_NET_CLS_IND is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# # Device Drivers # @@ -244,6 +494,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_IXP4XX=y # CONFIG_MTD_EDB7312 is not set # CONFIG_MTD_PCI is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -283,7 +534,6 @@ CONFIG_MTD_NAND_IDS=m # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -297,7 +547,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -351,6 +600,7 @@ CONFIG_BLK_DEV_CMD64X=y CONFIG_BLK_DEV_HPT366=y # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set CONFIG_BLK_DEV_PDC202XX_NEW=y @@ -369,6 +619,7 @@ CONFIG_BLK_DEV_IDEDMA=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -379,6 +630,7 @@ CONFIG_BLK_DEV_IDEDMA=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -391,235 +643,13 @@ CONFIG_BLK_DEV_IDEDMA=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=m -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_MULTIPATH=y -# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -CONFIG_INET_TUNNEL=m -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -CONFIG_IP_VS_DEBUG=y -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -# CONFIG_IP_VS_PROTO_TCP is not set -# CONFIG_IP_VS_PROTO_UDP is not set -# CONFIG_IP_VS_PROTO_ESP is not set -# CONFIG_IP_VS_PROTO_AH is not set - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -# CONFIG_IP_VS_SED is not set -# CONFIG_IP_VS_NQ is not set - -# -# IPVS application helper -# -# CONFIG_IPV6 is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# IP: Netfilter Configuration +# Network device support # -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_CT_ACCT is not set -# CONFIG_IP_NF_CONNTRACK_MARK is not set -# CONFIG_IP_NF_CT_PROTO_SCTP is not set -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_NF_AMANDA is not set -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -# CONFIG_IP_NF_MATCH_IPRANGE is not set -CONFIG_IP_NF_MATCH_MAC=m -# CONFIG_IP_NF_MATCH_PKTTYPE is not set -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_DSCP is not set -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -# CONFIG_IP_NF_MATCH_HELPER is not set -CONFIG_IP_NF_MATCH_STATE=m -# CONFIG_IP_NF_MATCH_CONNTRACK is not set -CONFIG_IP_NF_MATCH_OWNER=m -# CONFIG_IP_NF_MATCH_PHYSDEV is not set -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set -# CONFIG_IP_NF_MATCH_SCTP is not set -# CONFIG_IP_NF_MATCH_COMMENT is not set -# CONFIG_IP_NF_MATCH_HASHLIMIT is not set -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_SAME is not set -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_DSCP is not set -CONFIG_IP_NF_TARGET_MARK=m -# CONFIG_IP_NF_TARGET_CLASSIFY is not set -# CONFIG_IP_NF_RAW is not set -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -# CONFIG_IP_NF_ARP_MANGLE is not set - -# -# Bridge: Netfilter Configuration -# -# CONFIG_BRIDGE_NF_EBTABLES is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -CONFIG_ATM=y -CONFIG_ATM_CLIP=y -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -CONFIG_ATM_MPOA=m -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -# CONFIG_DECNET is not set -CONFIG_LLC=m -# CONFIG_LLC2 is not set -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -CONFIG_X25=m -CONFIG_LAPB=m -# CONFIG_NET_DIVERT is not set -CONFIG_ECONET=m -CONFIG_ECONET_AUNUDP=y -CONFIG_ECONET_NATIVE=y -CONFIG_WAN_ROUTER=m - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CLK_JIFFIES=y -# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set -# CONFIG_NET_SCH_CLK_CPU is not set -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -# CONFIG_NET_SCH_HFSC is not set -# CONFIG_NET_SCH_ATM is not set -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -# CONFIG_NET_SCH_NETEM is not set -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -# CONFIG_NET_CLS_BASIC is not set -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -# CONFIG_CLS_U32_PERF is not set -# CONFIG_NET_CLS_IND is not set -# CONFIG_CLS_U32_MARK is not set -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -# CONFIG_NET_EMATCH is not set -# CONFIG_NET_CLS_ACT is not set -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # ARCnet devices @@ -627,6 +657,11 @@ CONFIG_DUMMY=y # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y @@ -635,6 +670,7 @@ CONFIG_MII=y # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set # # Tulip family network device support @@ -671,13 +707,17 @@ CONFIG_EEPRO100=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -702,6 +742,7 @@ CONFIG_NET_RADIO=y CONFIG_HERMES=y # CONFIG_PLX_HERMES is not set # CONFIG_TMD_HERMES is not set +# CONFIG_NORTEL_HERMES is not set CONFIG_PCI_HERMES=y # CONFIG_ATMEL is not set @@ -709,6 +750,7 @@ CONFIG_PCI_HERMES=y # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support # # CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set CONFIG_NET_WIRELESS=y # @@ -758,6 +800,8 @@ CONFIG_ATM_TCP=m # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -795,7 +839,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # # CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y # # Character devices @@ -816,6 +859,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -882,12 +926,11 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_IOP3XX is not set -# CONFIG_I2C_ISA is not set CONFIG_I2C_IXP4XX=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set @@ -901,14 +944,33 @@ CONFIG_I2C_IXP4XX=y # CONFIG_I2C_PCA_ISA is not set # -# Hardware Sensors Chip support +# Miscellaneous I2C Chip support # -CONFIG_I2C_SENSOR=y +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set # CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set # CONFIG_SENSORS_FSCPOS is not set @@ -924,30 +986,26 @@ CONFIG_I2C_SENSOR=y # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set # -# Other I2C Chip support +# Misc devices # -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # -# Misc devices +# Multimedia Capabilities Port drivers # # @@ -994,6 +1052,7 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y # CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y @@ -1004,17 +1063,15 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -1034,12 +1091,10 @@ CONFIG_DNOTIFY=y # CONFIG_PROC_FS=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -1054,8 +1109,7 @@ CONFIG_RAMFS=y # CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y @@ -1072,12 +1126,14 @@ CONFIG_JFFS2_RTIME=y # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set @@ -1086,6 +1142,7 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -1124,6 +1181,7 @@ CONFIG_MSDOS_PARTITION=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1158,6 +1216,7 @@ CONFIG_DEBUG_LL=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y -- cgit v0.10.2 From 63c47c286d062d93e0501d60797274c84a587e97 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 26 Sep 2005 13:01:03 -0700 Subject: [IB] uverbs: Close some exploitable races Al Viro pointed out that the current IB userspace verbs interface allows userspace to cause mischief by closing file descriptors before we're ready, or issuing the same command twice at the same time. This patch closes those races, and fixes other obvious problems such as a module reference leak. Some other interface bogosities will require an ABI change to fix properly, so I'm deferring those fixes until 2.6.15. Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index b1897be..cc12434 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -69,6 +69,7 @@ struct ib_uverbs_event_file { struct ib_uverbs_file { struct kref ref; + struct semaphore mutex; struct ib_uverbs_device *device; struct ib_ucontext *ucontext; struct ib_event_handler event_handler; diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index e91ebde..5624451 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, struct ib_uverbs_get_context_resp resp; struct ib_udata udata; struct ib_device *ibdev = file->device->ib_dev; + struct ib_ucontext *ucontext; int i; - int ret = in_len; + int ret; if (out_len < sizeof resp) return -ENOSPC; @@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; + down(&file->mutex); + + if (file->ucontext) { + ret = -EINVAL; + goto err; + } + INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - file->ucontext = ibdev->alloc_ucontext(ibdev, &udata); - if (IS_ERR(file->ucontext)) { - ret = PTR_ERR(file->ucontext); - file->ucontext = NULL; - return ret; - } + ucontext = ibdev->alloc_ucontext(ibdev, &udata); + if (IS_ERR(ucontext)) + return PTR_ERR(file->ucontext); - file->ucontext->device = ibdev; - INIT_LIST_HEAD(&file->ucontext->pd_list); - INIT_LIST_HEAD(&file->ucontext->mr_list); - INIT_LIST_HEAD(&file->ucontext->mw_list); - INIT_LIST_HEAD(&file->ucontext->cq_list); - INIT_LIST_HEAD(&file->ucontext->qp_list); - INIT_LIST_HEAD(&file->ucontext->srq_list); - INIT_LIST_HEAD(&file->ucontext->ah_list); - spin_lock_init(&file->ucontext->lock); + ucontext->device = ibdev; + INIT_LIST_HEAD(&ucontext->pd_list); + INIT_LIST_HEAD(&ucontext->mr_list); + INIT_LIST_HEAD(&ucontext->mw_list); + INIT_LIST_HEAD(&ucontext->cq_list); + INIT_LIST_HEAD(&ucontext->qp_list); + INIT_LIST_HEAD(&ucontext->srq_list); + INIT_LIST_HEAD(&ucontext->ah_list); resp.async_fd = file->async_file.fd; for (i = 0; i < file->device->num_comp; ++i) if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab + i * sizeof (__u32), - &file->comp_file[i].fd, sizeof (__u32))) - goto err; + &file->comp_file[i].fd, sizeof (__u32))) { + ret = -EFAULT; + goto err_free; + } if (copy_to_user((void __user *) (unsigned long) cmd.response, - &resp, sizeof resp)) - goto err; + &resp, sizeof resp)) { + ret = -EFAULT; + goto err_free; + } + + file->ucontext = ucontext; + up(&file->mutex); return in_len; -err: - ibdev->dealloc_ucontext(file->ucontext); - file->ucontext = NULL; +err_free: + ibdev->dealloc_ucontext(ucontext); - return -EFAULT; +err: + up(&file->mutex); + return ret; } ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, @@ -352,9 +364,9 @@ retry: if (ret) goto err_pd; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->pd_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); memset(&resp, 0, sizeof resp); resp.pd_handle = uobj->id; @@ -368,9 +380,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); down(&ib_uverbs_idr_mutex); idr_remove(&ib_uverbs_pd_idr, uobj->id); @@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); kfree(uobj); @@ -512,9 +524,9 @@ retry: resp.mr_handle = obj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -527,9 +539,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&obj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_unreg: ib_dereg_mr(mr); @@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&memobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); ib_umem_release(file->device->ib_dev, &memobj->umem); kfree(memobj); @@ -647,9 +659,9 @@ retry: if (ret) goto err_cq; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); memset(&resp, 0, sizeof resp); resp.cq_handle = uobj->uobject.id; @@ -664,9 +676,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); down(&ib_uverbs_idr_mutex); idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); @@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->comp_file[0].lock); list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) { @@ -847,9 +859,9 @@ retry: resp.qp_handle = uobj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -862,9 +874,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_destroy: ib_destroy_qp(qp); @@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { @@ -1136,9 +1148,9 @@ retry: resp.srq_handle = uobj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -1151,9 +1163,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_destroy: ib_destroy_srq(srq); @@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index ce5bdb7..1251180 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if (hdr.in_words * 4 != count) return -EINVAL; - if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table)) + if (hdr.command < 0 || + hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || + !uverbs_cmd_table[hdr.command]) return -EINVAL; if (!file->ucontext && @@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) file = kmalloc(sizeof *file + (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file), GFP_KERNEL); - if (!file) - return -ENOMEM; + if (!file) { + ret = -ENOMEM; + goto err; + } file->device = dev; kref_init(&file->ref); + init_MUTEX(&file->mutex); file->ucontext = NULL; + kref_get(&file->ref); ret = ib_uverbs_event_init(&file->async_file, file); if (ret) - goto err; + goto err_kref; file->async_file.is_async = 1; - kref_get(&file->ref); - for (i = 0; i < dev->num_comp; ++i) { + kref_get(&file->ref); ret = ib_uverbs_event_init(&file->comp_file[i], file); if (ret) goto err_async; - kref_get(&file->ref); file->comp_file[i].is_async = 0; } @@ -524,9 +528,16 @@ err_async: ib_uverbs_event_release(&file->async_file); -err: +err_kref: + /* + * One extra kref_put() because we took a reference before the + * event file creation that failed and got us here. + */ + kref_put(&file->ref, ib_uverbs_release_file); kref_put(&file->ref, ib_uverbs_release_file); +err: + module_put(dev->ib_dev->owner); return ret; } diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index e16cf94..e6f4c9e 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -665,7 +665,6 @@ struct ib_ucontext { struct list_head qp_list; struct list_head srq_list; struct list_head ah_list; - spinlock_t lock; }; struct ib_uobject { -- cgit v0.10.2 From b9d717a7b413f227ebb2d61d9c118335f7292137 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 26 Sep 2005 14:28:02 -0700 Subject: [NET]: Make sure ctl buffer is aligned properly in sys_sendmsg(). It's on the stack and declared as "unsigned char[]", but pointers and similar can be in here thus we need to give it an explicit alignment attribute. Signed-off-by: Alex Williamson Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/socket.c b/net/socket.c index f926447..dbd1a68 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1700,7 +1700,9 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) struct socket *sock; char address[MAX_SOCK_ADDR]; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ + unsigned char ctl[sizeof(struct cmsghdr) + 20] + __attribute__ ((aligned (sizeof(__kernel_size_t)))); + /* 20 is size of ipv6_pktinfo */ unsigned char *ctl_buf = ctl; struct msghdr msg_sys; int err, ctl_len, iov_size, total_len; -- cgit v0.10.2 From acd042bb2de50d4e6fb969281a00cc8b8b71e46d Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Mon, 26 Sep 2005 15:06:50 -0700 Subject: [CONNECTOR]: async connector mode. If input message rate from userspace is too high, do not drop them, but try to deliver using work queue allocation. Failing there is some kind of congestion control. It also removes warn_on on this condition, which scares people. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 96663218..9f2f00d 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -31,16 +31,19 @@ #include #include -static void cn_queue_wrapper(void *data) +void cn_queue_wrapper(void *data) { - struct cn_callback_entry *cbq = data; + struct cn_callback_data *d = data; - cbq->cb->callback(cbq->cb->priv); - cbq->destruct_data(cbq->ddata); - cbq->ddata = NULL; + d->callback(d->callback_priv); + + d->destruct_data(d->ddata); + d->ddata = NULL; + + kfree(d->free); } -static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb) +static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *)) { struct cn_callback_entry *cbq; @@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac return NULL; } - cbq->cb = cb; - INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq); + snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name); + memcpy(&cbq->id.id, id, sizeof(struct cb_id)); + cbq->data.callback = callback; + + INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data); return cbq; } @@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2) return ((i1->idx == i2->idx) && (i1->val == i2->val)); } -int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) +int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)) { struct cn_callback_entry *cbq, *__cbq; int found = 0; - cbq = cn_queue_alloc_callback_entry(cb); + cbq = cn_queue_alloc_callback_entry(name, id, callback); if (!cbq) return -ENOMEM; @@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) spin_lock_bh(&dev->queue_lock); list_for_each_entry(__cbq, &dev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &cb->id)) { + if (cn_cb_equal(&__cbq->id.id, id)) { found = 1; break; } @@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) cbq->nls = dev->nls; cbq->seq = 0; - cbq->group = cbq->cb->id.idx; + cbq->group = cbq->id.id.idx; return 0; } @@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id) spin_lock_bh(&dev->queue_lock); list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) { - if (cn_cb_equal(&cbq->cb->id, id)) { + if (cn_cb_equal(&cbq->id.id, id)) { list_del(&cbq->callback_entry); found = 1; break; diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index aaf6d46..bb0b3a8 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask) spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { + if (cn_cb_equal(&__cbq->id.id, &msg->id)) { found = 1; group = __cbq->group; } @@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v { struct cn_callback_entry *__cbq; struct cn_dev *dev = &cdev; - int found = 0; + int err = -ENODEV; spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { - /* - * Let's scream if there is some magic and the - * data will arrive asynchronously here. - * [i.e. netlink messages will be queued]. - * After the first warning I will fix it - * quickly, but now I think it is - * impossible. --zbr (2004_04_27). - */ + if (cn_cb_equal(&__cbq->id.id, &msg->id)) { if (likely(!test_bit(0, &__cbq->work.pending) && - __cbq->ddata == NULL)) { - __cbq->cb->priv = msg; + __cbq->data.ddata == NULL)) { + __cbq->data.callback_priv = msg; - __cbq->ddata = data; - __cbq->destruct_data = destruct_data; + __cbq->data.ddata = data; + __cbq->data.destruct_data = destruct_data; if (queue_work(dev->cbdev->cn_queue, &__cbq->work)) - found = 1; + err = 0; } else { - printk("%s: cbq->data=%p, " - "work->pending=%08lx.\n", - __func__, __cbq->ddata, - __cbq->work.pending); - WARN_ON(1); + struct work_struct *w; + struct cn_callback_data *d; + + w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC); + if (w) { + d = (struct cn_callback_data *)(w+1); + + d->callback_priv = msg; + d->callback = __cbq->data.callback; + d->ddata = data; + d->destruct_data = destruct_data; + d->free = w; + + INIT_LIST_HEAD(&w->entry); + w->pending = 0; + w->func = &cn_queue_wrapper; + w->data = d; + init_timer(&w->timer); + + if (queue_work(dev->cbdev->cn_queue, w)) + err = 0; + else { + kfree(w); + err = -EINVAL; + } + } else + err = -ENOMEM; } break; } } spin_unlock_bh(&dev->cbdev->queue_lock); - return found ? 0 : -ENODEV; + return err; } /* @@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *)) { int err; struct cn_dev *dev = &cdev; - struct cn_callback *cb; - - cb = kzalloc(sizeof(*cb), GFP_KERNEL); - if (!cb) - return -ENOMEM; - - scnprintf(cb->name, sizeof(cb->name), "%s", name); - memcpy(&cb->id, id, sizeof(cb->id)); - cb->callback = callback; - - err = cn_queue_add_callback(dev->cbdev, cb); - if (err) { - kfree(cb); + err = cn_queue_add_callback(dev->cbdev, name, id, callback); + if (err) return err; - } cn_notify(id, 0); diff --git a/include/linux/connector.h b/include/linux/connector.h index 96de263..86d4b0a 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -104,12 +104,19 @@ struct cn_queue_dev { struct sock *nls; }; -struct cn_callback { +struct cn_callback_id { unsigned char name[CN_CBQ_NAMELEN]; - struct cb_id id; +}; + +struct cn_callback_data { + void (*destruct_data) (void *); + void *ddata; + + void *callback_priv; void (*callback) (void *); - void *priv; + + void *free; }; struct cn_callback_entry { @@ -118,8 +125,8 @@ struct cn_callback_entry { struct work_struct work; struct cn_queue_dev *pdev; - void (*destruct_data) (void *); - void *ddata; + struct cn_callback_id id; + struct cn_callback_data data; int seq, group; struct sock *nls; @@ -144,7 +151,7 @@ int cn_add_callback(struct cb_id *, char *, void (*callback) (void *)); void cn_del_callback(struct cb_id *); int cn_netlink_send(struct cn_msg *, u32, int); -int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb); +int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)); void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id); struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *); @@ -152,6 +159,8 @@ void cn_queue_free_dev(struct cn_queue_dev *dev); int cn_cb_equal(struct cb_id *, struct cb_id *); +void cn_queue_wrapper(void *data); + extern int cn_already_initialized; #endif /* __KERNEL__ */ -- cgit v0.10.2 From c62dba9011b93fd88fde929848582b2a98309878 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 26 Sep 2005 15:10:16 -0700 Subject: [IPV6]: Fix [Bug 5306] Oops on IPv6 route lookup > Steps to reproduce: > 1. Boot Linux, do NOT setup any IPv6 routes > 2. ip route get 2001::1 (or any unroutable address) Well caught. We never set rt6i_idev on ip6_null_entry. This patch should make the problem go away. Signed-off-by: Herbert Xu Acked-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2fea3f4..4e509e5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3520,6 +3520,8 @@ int __init addrconf_init(void) if (err) return err; + ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); + register_netdevice_notifier(&ipv6_dev_notf); #ifdef CONFIG_IPV6_PRIVACY -- cgit v0.10.2 From b85daee0e497c8fe7c4dc3531674ede645b37cdf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 26 Sep 2005 15:23:58 -0700 Subject: [AF_PACKET]: Remove bogus checks added to packet_sendmsg(). These broke existing apps, and the checks are superfluous as the values being verified aren't even used. Signed-off-by: David S. Miller diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ee865d8..6a67a87 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -761,12 +761,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, if (dev->hard_header) { int res; err = -EINVAL; - if (saddr) { - if (saddr->sll_halen != dev->addr_len) - goto out_free; - if (saddr->sll_hatype != dev->type) - goto out_free; - } res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); if (sock->type != SOCK_DGRAM) { skb->tail = skb->data; -- cgit v0.10.2 From 188bab3ae0ed164bc18f98be932512d777dd038b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 26 Sep 2005 15:25:11 -0700 Subject: [NETFILTER]: Fix invalid module autoloading by splitting iptable_nat When you've enabled conntrack and NAT as a module (standard case in all distributions), and you've also enabled the new conntrack netlink interface, loading ip_conntrack_netlink.ko will auto-load iptable_nat.ko. This causes a huge performance penalty, since for every packet you iterate the nat code, even if you don't want it. This patch splits iptable_nat.ko into the NAT core (ip_nat.ko) and the iptables frontend (iptable_nat.ko). Threfore, ip_conntrack_netlink.ko will only pull ip_nat.ko, but not the frontend. ip_nat.ko will "only" allocate some resources, but not affect runtime performance. This separation is also a nice step in anticipation of new packet filters (nf-hipac, ipset, pkttables) being able to use the NAT core. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h index 3b50eb9..30db23f 100644 --- a/include/linux/netfilter_ipv4/ip_nat_core.h +++ b/include/linux/netfilter_ipv4/ip_nat_core.h @@ -5,16 +5,14 @@ /* This header used to share core functionality between the standalone NAT module, and the compatibility layer's use of NAT for masquerading. */ -extern int ip_nat_init(void); -extern void ip_nat_cleanup(void); -extern unsigned int nat_packet(struct ip_conntrack *ct, +extern unsigned int ip_nat_packet(struct ip_conntrack *ct, enum ip_conntrack_info conntrackinfo, unsigned int hooknum, struct sk_buff **pskb); -extern int icmp_reply_translation(struct sk_buff **pskb, - struct ip_conntrack *ct, - enum ip_nat_manip_type manip, - enum ip_conntrack_dir dir); +extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_nat_manip_type manip, + enum ip_conntrack_dir dir); #endif /* _IP_NAT_CORE_H */ diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 8900253..dab4b58 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -4,7 +4,8 @@ # objects for the standalone - connection tracking / NAT ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o -iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o +ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o +iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o @@ -40,7 +41,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o # the three instances of ip_tables obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o -obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o +obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o ip_nat.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c3ea891..c5e3abd 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -74,12 +74,14 @@ ip_nat_proto_find_get(u_int8_t protonum) return p; } +EXPORT_SYMBOL_GPL(ip_nat_proto_find_get); void ip_nat_proto_put(struct ip_nat_protocol *p) { module_put(p->me); } +EXPORT_SYMBOL_GPL(ip_nat_proto_put); /* We keep an extra hash for each conntrack, for fast searching. */ static inline unsigned int @@ -111,6 +113,7 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) return csum_fold(csum_partial((char *)diffs, sizeof(diffs), oldcheck^0xFFFF)); } +EXPORT_SYMBOL(ip_nat_cheat_check); /* Is this tuple already taken? (not by us) */ int @@ -127,6 +130,7 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple, invert_tuplepr(&reply, tuple); return ip_conntrack_tuple_taken(&reply, ignored_conntrack); } +EXPORT_SYMBOL(ip_nat_used_tuple); /* If we source map this tuple so reply looks like reply_tuple, will * that meet the constraints of range. */ @@ -347,6 +351,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, return NF_ACCEPT; } +EXPORT_SYMBOL(ip_nat_setup_info); /* Returns true if succeeded. */ static int @@ -387,10 +392,10 @@ manip_pkt(u_int16_t proto, } /* Do packet manipulations according to ip_nat_setup_info. */ -unsigned int nat_packet(struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - struct sk_buff **pskb) +unsigned int ip_nat_packet(struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + unsigned int hooknum, + struct sk_buff **pskb) { enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); unsigned long statusbit; @@ -417,12 +422,13 @@ unsigned int nat_packet(struct ip_conntrack *ct, } return NF_ACCEPT; } +EXPORT_SYMBOL_GPL(ip_nat_packet); /* Dir is direction ICMP is coming from (opposite to packet it contains) */ -int icmp_reply_translation(struct sk_buff **pskb, - struct ip_conntrack *ct, - enum ip_nat_manip_type manip, - enum ip_conntrack_dir dir) +int ip_nat_icmp_reply_translation(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_nat_manip_type manip, + enum ip_conntrack_dir dir) { struct { struct icmphdr icmp; @@ -509,6 +515,7 @@ int icmp_reply_translation(struct sk_buff **pskb, return 1; } +EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation); /* Protocol registration. */ int ip_nat_protocol_register(struct ip_nat_protocol *proto) @@ -525,6 +532,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto) write_unlock_bh(&ip_nat_lock); return ret; } +EXPORT_SYMBOL(ip_nat_protocol_register); /* Noone stores the protocol anywhere; simply delete it. */ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) @@ -536,6 +544,7 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) /* Someone could be still looking at the proto in a bh. */ synchronize_net(); } +EXPORT_SYMBOL(ip_nat_protocol_unregister); #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) @@ -582,7 +591,7 @@ EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range); EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr); #endif -int __init ip_nat_init(void) +static int __init ip_nat_init(void) { size_t i; @@ -624,10 +633,14 @@ static int clean_nat(struct ip_conntrack *i, void *data) return 0; } -/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */ -void ip_nat_cleanup(void) +static void __exit ip_nat_cleanup(void) { ip_ct_iterate_cleanup(&clean_nat, NULL); ip_conntrack_destroyed = NULL; vfree(bysource); } + +MODULE_LICENSE("GPL"); + +module_init(ip_nat_init); +module_exit(ip_nat_cleanup); diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c index d2dd5d3..5d506e0 100644 --- a/net/ipv4/netfilter/ip_nat_helper.c +++ b/net/ipv4/netfilter/ip_nat_helper.c @@ -199,6 +199,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, } return 1; } +EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); /* Generic function for mangling variable-length address changes inside * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX @@ -256,6 +257,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, return 1; } +EXPORT_SYMBOL(ip_nat_mangle_udp_packet); /* Adjust one found SACK option including checksum correction */ static void @@ -399,6 +401,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb, return 1; } +EXPORT_SYMBOL(ip_nat_seq_adjust); /* Setup NAT on this expected conntrack so it follows master. */ /* If we fail to get a free NAT slot, we'll get dropped on confirm */ @@ -425,3 +428,4 @@ void ip_nat_follow_master(struct ip_conntrack *ct, /* hook doesn't matter, but it has to do destination manip */ ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); } +EXPORT_SYMBOL(ip_nat_follow_master); diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 0ff368b..30cd4e1 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -108,8 +108,8 @@ ip_nat_fn(unsigned int hooknum, case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - if (!icmp_reply_translation(pskb, ct, maniptype, - CTINFO2DIR(ctinfo))) + if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype, + CTINFO2DIR(ctinfo))) return NF_DROP; else return NF_ACCEPT; @@ -152,7 +152,7 @@ ip_nat_fn(unsigned int hooknum, } IP_NF_ASSERT(info); - return nat_packet(ct, ctinfo, hooknum, pskb); + return ip_nat_packet(ct, ctinfo, hooknum, pskb); } static unsigned int @@ -325,15 +325,10 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't setup rules.\n"); goto cleanup_nothing; } - ret = ip_nat_init(); - if (ret < 0) { - printk("ip_nat_init: can't setup rules.\n"); - goto cleanup_rule_init; - } ret = nf_register_hook(&ip_nat_in_ops); if (ret < 0) { printk("ip_nat_init: can't register in hook.\n"); - goto cleanup_nat; + goto cleanup_rule_init; } ret = nf_register_hook(&ip_nat_out_ops); if (ret < 0) { @@ -374,8 +369,6 @@ static int init_or_cleanup(int init) nf_unregister_hook(&ip_nat_out_ops); cleanup_inops: nf_unregister_hook(&ip_nat_in_ops); - cleanup_nat: - ip_nat_cleanup(); cleanup_rule_init: ip_nat_rule_cleanup(); cleanup_nothing: @@ -395,14 +388,4 @@ static void __exit fini(void) module_init(init); module_exit(fini); -EXPORT_SYMBOL(ip_nat_setup_info); -EXPORT_SYMBOL(ip_nat_protocol_register); -EXPORT_SYMBOL(ip_nat_protocol_unregister); -EXPORT_SYMBOL_GPL(ip_nat_proto_find_get); -EXPORT_SYMBOL_GPL(ip_nat_proto_put); -EXPORT_SYMBOL(ip_nat_cheat_check); -EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); -EXPORT_SYMBOL(ip_nat_mangle_udp_packet); -EXPORT_SYMBOL(ip_nat_used_tuple); -EXPORT_SYMBOL(ip_nat_follow_master); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From c4a3e0a529ab3e65223e81681c7c6b1bc188fa58 Mon Sep 17 00:00:00 2001 From: "Bagalkote, Sreenivas" Date: Tue, 20 Sep 2005 17:46:58 -0400 Subject: [SCSI] MegaRAID SAS RAID: new driver Signed-off-by: Sreenivas Bagalkote Signed-off-by: James Bottomley diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 1e4edbd..48529d1 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_DC390T) += tmscsim.o obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ +obj-$(CONFIG_MEGARAID_SAS) += megaraid/ obj-$(CONFIG_SCSI_ACARD) += atp870u.o obj-$(CONFIG_SCSI_SUNESP) += esp.o obj-$(CONFIG_SCSI_GDTH) += gdth.o diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid index 917d591..7363e12 100644 --- a/drivers/scsi/megaraid/Kconfig.megaraid +++ b/drivers/scsi/megaraid/Kconfig.megaraid @@ -76,3 +76,12 @@ config MEGARAID_LEGACY To compile this driver as a module, choose M here: the module will be called megaraid endif + +config MEGARAID_SAS + tristate "LSI Logic MegaRAID SAS RAID Module" + depends on PCI && SCSI + help + Module for LSI Logic's SAS based RAID controllers. + To compile this driver as a module, choose 'm' here. + Module will be called megaraid_sas + diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile index 6dd99f2..f469915 100644 --- a/drivers/scsi/megaraid/Makefile +++ b/drivers/scsi/megaraid/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o +obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c new file mode 100644 index 0000000..1b3148e --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -0,0 +1,2805 @@ +/* + * + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2003-2005 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_sas.c + * Version : v00.00.02.00-rc4 + * + * Authors: + * Sreenivas Bagalkote + * Sumant Patro + * + * List of supported controllers + * + * OEM Product Name VID DID SSVID SSID + * --- ------------ --- --- ---- ---- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "megaraid_sas.h" + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MEGASAS_VERSION); +MODULE_AUTHOR("sreenivas.bagalkote@lsil.com"); +MODULE_DESCRIPTION("LSI Logic MegaRAID SAS Driver"); + +/* + * PCI ID table for all supported controllers + */ +static struct pci_device_id megasas_pci_table[] = { + + { + PCI_VENDOR_ID_LSI_LOGIC, + PCI_DEVICE_ID_LSI_SAS1064R, + PCI_ANY_ID, + PCI_ANY_ID, + }, + { + PCI_VENDOR_ID_DELL, + PCI_DEVICE_ID_DELL_PERC5, + PCI_ANY_ID, + PCI_ANY_ID, + }, + {0} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, megasas_pci_table); + +static int megasas_mgmt_majorno; +static struct megasas_mgmt_info megasas_mgmt_info; +static struct fasync_struct *megasas_async_queue; +static DECLARE_MUTEX(megasas_async_queue_mutex); + +/** + * megasas_get_cmd - Get a command from the free pool + * @instance: Adapter soft state + * + * Returns a free command from the pool + */ +static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance + *instance) +{ + unsigned long flags; + struct megasas_cmd *cmd = NULL; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + if (!list_empty(&instance->cmd_pool)) { + cmd = list_entry((&instance->cmd_pool)->next, + struct megasas_cmd, list); + list_del_init(&cmd->list); + } else { + printk(KERN_ERR "megasas: Command pool empty!\n"); + } + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); + return cmd; +} + +/** + * megasas_return_cmd - Return a cmd to free command pool + * @instance: Adapter soft state + * @cmd: Command packet to be returned to free command pool + */ +static inline void +megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + cmd->scmd = NULL; + list_add_tail(&cmd->list, &instance->cmd_pool); + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); +} + +/** + * megasas_enable_intr - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr(struct megasas_register_set __iomem * regs) +{ + writel(1, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr - Disables interrupts + * @regs: MFI register set + */ +static inline void +megasas_disable_intr(struct megasas_register_set __iomem * regs) +{ + u32 mask = readl(®s->outbound_intr_mask) & (~0x00000001); + writel(mask, ®s->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_issue_polled - Issues a polling command + * @instance: Adapter soft state + * @cmd: Command packet to be issued + * + * For polling, MFI requires the cmd_status to be set to 0xFF before posting. + */ +static int +megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + int i; + u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; + + struct megasas_header *frame_hdr = &cmd->frame->hdr; + + frame_hdr->cmd_status = 0xFF; + frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + + /* + * Issue the frame using inbound queue port + */ + writel(cmd->frame_phys_addr >> 3, + &instance->reg_set->inbound_queue_port); + + /* + * Wait for cmd_status to change + */ + for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { + rmb(); + msleep(1); + } + + if (frame_hdr->cmd_status == 0xff) + return -ETIME; + + return 0; +} + +/** + * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds + * @instance: Adapter soft state + * @cmd: Command to be issued + * + * This function waits on an event for the command to be returned from ISR. + * Used to issue ioctl commands. + */ +static int +megasas_issue_blocked_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = ENODATA; + + writel(cmd->frame_phys_addr >> 3, + &instance->reg_set->inbound_queue_port); + + wait_event(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA)); + + return 0; +} + +/** + * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd + * @instance: Adapter soft state + * @cmd_to_abort: Previously issued cmd to be aborted + * + * MFI firmware can abort previously issued AEN comamnd (automatic event + * notification). The megasas_issue_blocked_abort_cmd() issues such abort + * cmd and blocks till it is completed. + */ +static int +megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd_to_abort) +{ + struct megasas_cmd *cmd; + struct megasas_abort_frame *abort_fr; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -1; + + abort_fr = &cmd->frame->abort; + + /* + * Prepare and issue the abort frame + */ + abort_fr->cmd = MFI_CMD_ABORT; + abort_fr->cmd_status = 0xFF; + abort_fr->flags = 0; + abort_fr->abort_context = cmd_to_abort->index; + abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr; + abort_fr->abort_mfi_phys_addr_hi = 0; + + cmd->sync_cmd = 1; + cmd->cmd_status = 0xFF; + + writel(cmd->frame_phys_addr >> 3, + &instance->reg_set->inbound_queue_port); + + /* + * Wait for this cmd to complete + */ + wait_event(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF)); + + megasas_return_cmd(instance, cmd); + return 0; +} + +/** + * megasas_make_sgl32 - Prepares 32-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static inline int +megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + /* + * Return 0 if there is no data transfer + */ + if (!scp->request_buffer || !scp->request_bufflen) + return 0; + + if (!scp->use_sg) { + mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev, + scp-> + request_buffer, + scp-> + request_bufflen, + scp-> + sc_data_direction); + mfi_sgl->sge32[0].length = scp->request_bufflen; + + return 1; + } + + os_sgl = (struct scatterlist *)scp->request_buffer; + sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, + scp->sc_data_direction); + + for (i = 0; i < sge_count; i++, os_sgl++) { + mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); + } + + return sge_count; +} + +/** + * megasas_make_sgl64 - Prepares 64-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static inline int +megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + /* + * Return 0 if there is no data transfer + */ + if (!scp->request_buffer || !scp->request_bufflen) + return 0; + + if (!scp->use_sg) { + mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev, + scp-> + request_buffer, + scp-> + request_bufflen, + scp-> + sc_data_direction); + + mfi_sgl->sge64[0].length = scp->request_bufflen; + + return 1; + } + + os_sgl = (struct scatterlist *)scp->request_buffer; + sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg, + scp->sc_data_direction); + + for (i = 0; i < sge_count; i++, os_sgl++) { + mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); + } + + return sge_count; +} + +/** + * megasas_build_dcdb - Prepares a direct cdb (DCDB) command + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared in + * + * This function prepares CDB commands. These are typcially pass-through + * commands to the devices. + */ +static inline int +megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 sge_sz; + int sge_bytes; + u32 is_logical; + u32 device_id; + u16 flags = 0; + struct megasas_pthru_frame *pthru; + + is_logical = MEGASAS_IS_LOGICAL(scp); + device_id = MEGASAS_DEV_INDEX(instance, scp); + pthru = (struct megasas_pthru_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + else if (scp->sc_data_direction == PCI_DMA_NONE) + flags = MFI_FRAME_DIR_NONE; + + /* + * Prepare the DCDB frame + */ + pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO; + pthru->cmd_status = 0x0; + pthru->scsi_status = 0x0; + pthru->target_id = device_id; + pthru->lun = scp->device->lun; + pthru->cdb_len = scp->cmd_len; + pthru->timeout = 0; + pthru->flags = flags; + pthru->data_xfer_len = scp->request_bufflen; + + memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); + + /* + * Construct SGL + */ + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + if (IS_DMA64) { + pthru->flags |= MFI_FRAME_SGL64; + pthru->sge_count = megasas_make_sgl64(instance, scp, + &pthru->sgl); + } else + pthru->sge_count = megasas_make_sgl32(instance, scp, + &pthru->sgl); + + /* + * Sense info specific + */ + pthru->sense_len = SCSI_SENSE_BUFFERSIZE; + pthru->sense_buf_phys_addr_hi = 0; + pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + sge_bytes = sge_sz * pthru->sge_count; + + /* + * Compute the total number of frames this command consumes. FW uses + * this number to pull sufficient number of frames from host memory. + */ + cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + + ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1; + + if (cmd->frame_count > 7) + cmd->frame_count = 8; + + return cmd->frame_count; +} + +/** + * megasas_build_ldio - Prepares IOs to logical devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to to be prepared + * + * Frames (and accompanying SGLs) for regular SCSI IOs use this function. + */ +static inline int +megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 sge_sz; + int sge_bytes; + u32 device_id; + u8 sc = scp->cmnd[0]; + u16 flags = 0; + struct megasas_io_frame *ldio; + + device_id = MEGASAS_DEV_INDEX(instance, scp); + ldio = (struct megasas_io_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + + /* + * Preare the Logical IO frame: 2nd bit is zero for all read cmds + */ + ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; + ldio->cmd_status = 0x0; + ldio->scsi_status = 0x0; + ldio->target_id = device_id; + ldio->timeout = 0; + ldio->reserved_0 = 0; + ldio->pad_0 = 0; + ldio->flags = flags; + ldio->start_lba_hi = 0; + ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0; + + /* + * 6-byte READ(0x08) or WRITE(0x0A) cdb + */ + if (scp->cmd_len == 6) { + ldio->lba_count = (u32) scp->cmnd[4]; + ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) | + ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; + + ldio->start_lba_lo &= 0x1FFFFF; + } + + /* + * 10-byte READ(0x28) or WRITE(0x2A) cdb + */ + else if (scp->cmd_len == 10) { + ldio->lba_count = (u32) scp->cmnd[8] | + ((u32) scp->cmnd[7] << 8); + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 12-byte READ(0xA8) or WRITE(0xAA) cdb + */ + else if (scp->cmd_len == 12) { + ldio->lba_count = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 16-byte READ(0x88) or WRITE(0x8A) cdb + */ + else if (scp->cmd_len == 16) { + ldio->lba_count = ((u32) scp->cmnd[10] << 24) | + ((u32) scp->cmnd[11] << 16) | + ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; + + ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + + } + + /* + * Construct SGL + */ + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + if (IS_DMA64) { + ldio->flags |= MFI_FRAME_SGL64; + ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); + } else + ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); + + /* + * Sense info specific + */ + ldio->sense_len = SCSI_SENSE_BUFFERSIZE; + ldio->sense_buf_phys_addr_hi = 0; + ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + sge_bytes = sge_sz * ldio->sge_count; + + cmd->frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + + ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) + 1; + + if (cmd->frame_count > 7) + cmd->frame_count = 8; + + return cmd->frame_count; +} + +/** + * megasas_build_cmd - Prepares a command packet + * @instance: Adapter soft state + * @scp: SCSI command + * @frame_count: [OUT] Number of frames used to prepare this command + */ +static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance + *instance, + struct scsi_cmnd *scp, + int *frame_count) +{ + u32 logical_cmd; + struct megasas_cmd *cmd; + + /* + * Find out if this is logical or physical drive command. + */ + logical_cmd = MEGASAS_IS_LOGICAL(scp); + + /* + * Logical drive command + */ + if (logical_cmd) { + + if (scp->device->id >= MEGASAS_MAX_LD) { + scp->result = DID_BAD_TARGET << 16; + return NULL; + } + + switch (scp->cmnd[0]) { + + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + case READ_16: + case WRITE_16: + /* + * Fail for LUN > 0 + */ + if (scp->device->lun) { + scp->result = DID_BAD_TARGET << 16; + return NULL; + } + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + scp->result = DID_IMM_RETRY << 16; + return NULL; + } + + *frame_count = megasas_build_ldio(instance, scp, cmd); + + if (!(*frame_count)) { + megasas_return_cmd(instance, cmd); + return NULL; + } + + return cmd; + + default: + /* + * Fail for LUN > 0 + */ + if (scp->device->lun) { + scp->result = DID_BAD_TARGET << 16; + return NULL; + } + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + scp->result = DID_IMM_RETRY << 16; + return NULL; + } + + *frame_count = megasas_build_dcdb(instance, scp, cmd); + + if (!(*frame_count)) { + megasas_return_cmd(instance, cmd); + return NULL; + } + + return cmd; + } + } else { + cmd = megasas_get_cmd(instance); + + if (!cmd) { + scp->result = DID_IMM_RETRY << 16; + return NULL; + } + + *frame_count = megasas_build_dcdb(instance, scp, cmd); + + if (!(*frame_count)) { + megasas_return_cmd(instance, cmd); + return NULL; + } + + return cmd; + } + + return NULL; +} + +/** + * megasas_queue_command - Queue entry point + * @scmd: SCSI command to be queued + * @done: Callback entry point + */ +static int +megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) +{ + u32 frame_count; + unsigned long flags; + struct megasas_cmd *cmd; + struct megasas_instance *instance; + + instance = (struct megasas_instance *) + scmd->device->host->hostdata; + scmd->scsi_done = done; + scmd->result = 0; + + cmd = megasas_build_cmd(instance, scmd, &frame_count); + + if (!cmd) { + done(scmd); + return 0; + } + + cmd->scmd = scmd; + scmd->SCp.ptr = (char *)cmd; + scmd->SCp.sent_command = jiffies; + + /* + * Issue the command to the FW + */ + spin_lock_irqsave(&instance->instance_lock, flags); + instance->fw_outstanding++; + spin_unlock_irqrestore(&instance->instance_lock, flags); + + writel(((cmd->frame_phys_addr >> 3) | (cmd->frame_count - 1)), + &instance->reg_set->inbound_queue_port); + + return 0; +} + +/** + * megasas_wait_for_outstanding - Wait for all outstanding cmds + * @instance: Adapter soft state + * + * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to + * complete all its outstanding commands. Returns error if one or more IOs + * are pending after this time period. It also marks the controller dead. + */ +static int megasas_wait_for_outstanding(struct megasas_instance *instance) +{ + int i; + u32 wait_time = MEGASAS_RESET_WAIT_TIME; + + for (i = 0; i < wait_time; i++) { + + if (!instance->fw_outstanding) + break; + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + "commands to complete\n", i, + instance->fw_outstanding); + } + + msleep(1000); + } + + if (instance->fw_outstanding) { + instance->hw_crit_error = 1; + return FAILED; + } + + return SUCCESS; +} + +/** + * megasas_generic_reset - Generic reset routine + * @scmd: Mid-layer SCSI command + * + * This routine implements a generic reset handler for device, bus and host + * reset requests. Device, bus and host specific reset handlers can use this + * function after they do their specific tasks. + */ +static int megasas_generic_reset(struct scsi_cmnd *scmd) +{ + int ret_val; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + printk(KERN_NOTICE "megasas: RESET -%ld cmd=%x \n", + scmd->serial_number, scmd->cmnd[0], scmd->device->channel, + scmd->device->id, scmd->device->lun); + + if (instance->hw_crit_error) { + printk(KERN_ERR "megasas: cannot recover from previous reset " + "failures\n"); + return FAILED; + } + + spin_unlock(scmd->device->host->host_lock); + + ret_val = megasas_wait_for_outstanding(instance); + + if (ret_val == SUCCESS) + printk(KERN_NOTICE "megasas: reset successful \n"); + else + printk(KERN_ERR "megasas: failed to do reset\n"); + + spin_lock(scmd->device->host->host_lock); + + return ret_val; +} + +static enum scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) +{ + unsigned long seconds; + + if (scmd->SCp.ptr) { + seconds = (jiffies - scmd->SCp.sent_command) / HZ; + + if (seconds < 90) { + return EH_RESET_TIMER; + } else { + return EH_NOT_HANDLED; + } + } + + return EH_HANDLED; +} + +/** + * megasas_reset_device - Device reset handler entry point + */ +static int megasas_reset_device(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * First wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_reset_bus_host - Bus & host reset handler entry point + */ +static int megasas_reset_bus_host(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * Frist wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_service_aen - Processes an event notification + * @instance: Adapter soft state + * @cmd: AEN command completed by the ISR + * + * For AEN, driver sends a command down to FW that is held by the FW till an + * event occurs. When an event of interest occurs, FW completes the command + * that it was previously holding. + * + * This routines sends SIGIO signal to processes that have registered with the + * driver for AEN. + */ +static void +megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + /* + * Don't signal app if it is just an aborted previously registered aen + */ + if (!cmd->abort_aen) + kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); + else + cmd->abort_aen = 0; + + instance->aen_cmd = NULL; + megasas_return_cmd(instance, cmd); +} + +/* + * Scsi host template for megaraid_sas driver + */ +static struct scsi_host_template megasas_template = { + + .module = THIS_MODULE, + .name = "LSI Logic SAS based MegaRAID driver", + .proc_name = "megaraid_sas", + .queuecommand = megasas_queue_command, + .eh_device_reset_handler = megasas_reset_device, + .eh_bus_reset_handler = megasas_reset_bus_host, + .eh_host_reset_handler = megasas_reset_bus_host, + .eh_timed_out = megasas_reset_timer, + .use_clustering = ENABLE_CLUSTERING, +}; + +/** + * megasas_complete_int_cmd - Completes an internal command + * @instance: Adapter soft state + * @cmd: Command to be completed + * + * The megasas_issue_blocked_cmd() function waits for a command to complete + * after it issues a command. This function wakes up that waiting routine by + * calling wake_up() on the wait queue. + */ +static void +megasas_complete_int_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = cmd->frame->io.cmd_status; + + if (cmd->cmd_status == ENODATA) { + cmd->cmd_status = 0; + } + wake_up(&instance->int_cmd_wait_q); +} + +/** + * megasas_complete_abort - Completes aborting a command + * @instance: Adapter soft state + * @cmd: Cmd that was issued to abort another cmd + * + * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q + * after it issues an abort on a previously issued command. This function + * wakes up all functions waiting on the same wait queue. + */ +static void +megasas_complete_abort(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + cmd->cmd_status = 0; + wake_up(&instance->abort_cmd_wait_q); + } + + return; +} + +/** + * megasas_unmap_sgbuf - Unmap SG buffers + * @instance: Adapter soft state + * @cmd: Completed command + */ +static inline void +megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + dma_addr_t buf_h; + u8 opcode; + + if (cmd->scmd->use_sg) { + pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer, + cmd->scmd->use_sg, cmd->scmd->sc_data_direction); + return; + } + + if (!cmd->scmd->request_bufflen) + return; + + opcode = cmd->frame->hdr.cmd; + + if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) { + if (IS_DMA64) + buf_h = cmd->frame->io.sgl.sge64[0].phys_addr; + else + buf_h = cmd->frame->io.sgl.sge32[0].phys_addr; + } else { + if (IS_DMA64) + buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr; + else + buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr; + } + + pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen, + cmd->scmd->sc_data_direction); + return; +} + +/** + * megasas_complete_cmd - Completes a command + * @instance: Adapter soft state + * @cmd: Command to be completed + * @alt_status: If non-zero, use this value as status to + * SCSI mid-layer instead of the value returned + * by the FW. This should be used if caller wants + * an alternate status (as in the case of aborted + * commands) + */ +static inline void +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, + u8 alt_status) +{ + int exception = 0; + struct megasas_header *hdr = &cmd->frame->hdr; + unsigned long flags; + + if (cmd->scmd) { + cmd->scmd->SCp.ptr = (char *)0; + } + + switch (hdr->cmd) { + + case MFI_CMD_PD_SCSI_IO: + case MFI_CMD_LD_SCSI_IO: + + /* + * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been + * issued either through an IO path or an IOCTL path. If it + * was via IOCTL, we will send it to internal completion. + */ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + megasas_complete_int_cmd(instance, cmd); + break; + } + + /* + * Don't export physical disk devices to mid-layer. + */ + if (!MEGASAS_IS_LOGICAL(cmd->scmd) && + (hdr->cmd_status == MFI_STAT_OK) && + (cmd->scmd->cmnd[0] == INQUIRY)) { + + if (((*(u8 *) cmd->scmd->request_buffer) & 0x1F) == + TYPE_DISK) { + cmd->scmd->result = DID_BAD_TARGET << 16; + exception = 1; + } + } + + case MFI_CMD_LD_READ: + case MFI_CMD_LD_WRITE: + + if (alt_status) { + cmd->scmd->result = alt_status << 16; + exception = 1; + } + + if (exception) { + + spin_lock_irqsave(&instance->instance_lock, flags); + instance->fw_outstanding--; + spin_unlock_irqrestore(&instance->instance_lock, flags); + + megasas_unmap_sgbuf(instance, cmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + } + + switch (hdr->cmd_status) { + + case MFI_STAT_OK: + cmd->scmd->result = DID_OK << 16; + break; + + case MFI_STAT_SCSI_IO_FAILED: + case MFI_STAT_LD_INIT_IN_PROGRESS: + cmd->scmd->result = + (DID_ERROR << 16) | hdr->scsi_status; + break; + + case MFI_STAT_SCSI_DONE_WITH_ERROR: + + cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status; + + if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) { + memset(cmd->scmd->sense_buffer, 0, + SCSI_SENSE_BUFFERSIZE); + memcpy(cmd->scmd->sense_buffer, cmd->sense, + hdr->sense_len); + + cmd->scmd->result |= DRIVER_SENSE << 24; + } + + break; + + case MFI_STAT_LD_OFFLINE: + case MFI_STAT_DEVICE_NOT_FOUND: + cmd->scmd->result = DID_BAD_TARGET << 16; + break; + + default: + printk(KERN_DEBUG "megasas: MFI FW status %#x\n", + hdr->cmd_status); + cmd->scmd->result = DID_ERROR << 16; + break; + } + + spin_lock_irqsave(&instance->instance_lock, flags); + instance->fw_outstanding--; + spin_unlock_irqrestore(&instance->instance_lock, flags); + + megasas_unmap_sgbuf(instance, cmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + + case MFI_CMD_SMP: + case MFI_CMD_STP: + case MFI_CMD_DCMD: + + /* + * See if got an event notification + */ + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) + megasas_service_aen(instance, cmd); + else + megasas_complete_int_cmd(instance, cmd); + + break; + + case MFI_CMD_ABORT: + /* + * Cmd issued to abort another cmd returned + */ + megasas_complete_abort(instance, cmd); + break; + + default: + printk("megasas: Unknown command completed! [0x%X]\n", + hdr->cmd); + break; + } +} + +/** + * megasas_deplete_reply_queue - Processes all completed commands + * @instance: Adapter soft state + * @alt_status: Alternate status to be returned to + * SCSI mid-layer instead of the status + * returned by the FW + */ +static inline int +megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) +{ + u32 status; + u32 producer; + u32 consumer; + u32 context; + struct megasas_cmd *cmd; + + /* + * Check if it is our interrupt + */ + status = readl(&instance->reg_set->outbound_intr_status); + + if (!(status & MFI_OB_INTR_STATUS_MASK)) { + return IRQ_NONE; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, &instance->reg_set->outbound_intr_status); + + producer = *instance->producer; + consumer = *instance->consumer; + + while (consumer != producer) { + context = instance->reply_queue[consumer]; + + cmd = instance->cmd_list[context]; + + megasas_complete_cmd(instance, cmd, alt_status); + + consumer++; + if (consumer == (instance->max_fw_cmds + 1)) { + consumer = 0; + } + } + + *instance->consumer = producer; + + return IRQ_HANDLED; +} + +/** + * megasas_isr - isr entry point + */ +static irqreturn_t megasas_isr(int irq, void *devp, struct pt_regs *regs) +{ + return megasas_deplete_reply_queue((struct megasas_instance *)devp, + DID_OK); +} + +/** + * megasas_transition_to_ready - Move the FW to READY state + * @reg_set: MFI register set + * + * During the initialization, FW passes can potentially be in any one of + * several possible states. If the FW in operational, waiting-for-handshake + * states, driver must take steps to bring it to ready state. Otherwise, it + * has to wait for the ready state. + */ +static int +megasas_transition_to_ready(struct megasas_register_set __iomem * reg_set) +{ + int i; + u8 max_wait; + u32 fw_state; + u32 cur_state; + + fw_state = readl(®_set->outbound_msg_0) & MFI_STATE_MASK; + + while (fw_state != MFI_STATE_READY) { + + printk(KERN_INFO "megasas: Waiting for FW to come to ready" + " state\n"); + switch (fw_state) { + + case MFI_STATE_FAULT: + + printk(KERN_DEBUG "megasas: FW in FAULT state!!\n"); + return -ENODEV; + + case MFI_STATE_WAIT_HANDSHAKE: + /* + * Set the CLR bit in inbound doorbell + */ + writel(MFI_INIT_CLEAR_HANDSHAKE, + ®_set->inbound_doorbell); + + max_wait = 2; + cur_state = MFI_STATE_WAIT_HANDSHAKE; + break; + + case MFI_STATE_OPERATIONAL: + /* + * Bring it to READY state; assuming max wait 2 secs + */ + megasas_disable_intr(reg_set); + writel(MFI_INIT_READY, ®_set->inbound_doorbell); + + max_wait = 10; + cur_state = MFI_STATE_OPERATIONAL; + break; + + case MFI_STATE_UNDEFINED: + /* + * This state should not last for more than 2 seconds + */ + max_wait = 2; + cur_state = MFI_STATE_UNDEFINED; + break; + + case MFI_STATE_BB_INIT: + max_wait = 2; + cur_state = MFI_STATE_BB_INIT; + break; + + case MFI_STATE_FW_INIT: + max_wait = 20; + cur_state = MFI_STATE_FW_INIT; + break; + + case MFI_STATE_FW_INIT_2: + max_wait = 20; + cur_state = MFI_STATE_FW_INIT_2; + break; + + case MFI_STATE_DEVICE_SCAN: + max_wait = 20; + cur_state = MFI_STATE_DEVICE_SCAN; + break; + + case MFI_STATE_FLUSH_CACHE: + max_wait = 20; + cur_state = MFI_STATE_FLUSH_CACHE; + break; + + default: + printk(KERN_DEBUG "megasas: Unknown state 0x%x\n", + fw_state); + return -ENODEV; + } + + /* + * The cur_state should not last for more than max_wait secs + */ + for (i = 0; i < (max_wait * 1000); i++) { + fw_state = MFI_STATE_MASK & + readl(®_set->outbound_msg_0); + + if (fw_state == cur_state) { + msleep(1); + } else + break; + } + + /* + * Return error if fw_state hasn't changed after max_wait + */ + if (fw_state == cur_state) { + printk(KERN_DEBUG "FW state [%d] hasn't changed " + "in %d secs\n", fw_state, max_wait); + return -ENODEV; + } + }; + + return 0; +} + +/** + * megasas_teardown_frame_pool - Destroy the cmd frame DMA pool + * @instance: Adapter soft state + */ +static void megasas_teardown_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd = instance->max_fw_cmds; + struct megasas_cmd *cmd; + + if (!instance->frame_dma_pool) + return; + + /* + * Return all frames to pool + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + if (cmd->frame) + pci_pool_free(instance->frame_dma_pool, cmd->frame, + cmd->frame_phys_addr); + + if (cmd->sense) + pci_pool_free(instance->sense_dma_pool, cmd->frame, + cmd->sense_phys_addr); + } + + /* + * Now destroy the pool itself + */ + pci_pool_destroy(instance->frame_dma_pool); + pci_pool_destroy(instance->sense_dma_pool); + + instance->frame_dma_pool = NULL; + instance->sense_dma_pool = NULL; +} + +/** + * megasas_create_frame_pool - Creates DMA pool for cmd frames + * @instance: Adapter soft state + * + * Each command packet has an embedded DMA memory buffer that is used for + * filling MFI frame and the SG list that immediately follows the frame. This + * function creates those DMA memory buffers for each command packet by using + * PCI pool facility. + */ +static int megasas_create_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd; + u32 sge_sz; + u32 sgl_sz; + u32 total_sz; + u32 frame_count; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * Size of our frame is 64 bytes for MFI frame, followed by max SG + * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer + */ + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + /* + * Calculated the number of 64byte frames required for SGL + */ + sgl_sz = sge_sz * instance->max_num_sge; + frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE; + + /* + * We need one extra frame for the MFI command + */ + frame_count++; + + total_sz = MEGAMFI_FRAME_SIZE * frame_count; + /* + * Use DMA pool facility provided by PCI layer + */ + instance->frame_dma_pool = pci_pool_create("megasas frame pool", + instance->pdev, total_sz, 64, + 0); + + if (!instance->frame_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup frame pool\n"); + return -ENOMEM; + } + + instance->sense_dma_pool = pci_pool_create("megasas sense pool", + instance->pdev, 128, 4, 0); + + if (!instance->sense_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup sense pool\n"); + + pci_pool_destroy(instance->frame_dma_pool); + instance->frame_dma_pool = NULL; + + return -ENOMEM; + } + + /* + * Allocate and attach a frame to each of the commands in cmd_list. + * By making cmd->index as the context instead of the &cmd, we can + * always use 32bit context regardless of the architecture + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + cmd->frame = pci_pool_alloc(instance->frame_dma_pool, + GFP_KERNEL, &cmd->frame_phys_addr); + + cmd->sense = pci_pool_alloc(instance->sense_dma_pool, + GFP_KERNEL, &cmd->sense_phys_addr); + + /* + * megasas_teardown_frame_pool() takes care of freeing + * whatever has been allocated + */ + if (!cmd->frame || !cmd->sense) { + printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n"); + megasas_teardown_frame_pool(instance); + return -ENOMEM; + } + + cmd->frame->io.context = cmd->index; + } + + return 0; +} + +/** + * megasas_free_cmds - Free all the cmds in the free cmd pool + * @instance: Adapter soft state + */ +static void megasas_free_cmds(struct megasas_instance *instance) +{ + int i; + /* First free the MFI frame pool */ + megasas_teardown_frame_pool(instance); + + /* Free all the commands in the cmd_list */ + for (i = 0; i < instance->max_fw_cmds; i++) + kfree(instance->cmd_list[i]); + + /* Free the cmd_list buffer itself */ + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + INIT_LIST_HEAD(&instance->cmd_pool); +} + +/** + * megasas_alloc_cmds - Allocates the command packets + * @instance: Adapter soft state + * + * Each command that is issued to the FW, whether IO commands from the OS or + * internal commands like IOCTLs, are wrapped in local data structure called + * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to + * the FW. + * + * Each frame has a 32-bit field called context (tag). This context is used + * to get back the megasas_cmd from the frame when a frame gets completed in + * the ISR. Typically the address of the megasas_cmd itself would be used as + * the context. But we wanted to keep the differences between 32 and 64 bit + * systems to the mininum. We always use 32 bit integers for the context. In + * this driver, the 32 bit values are the indices into an array cmd_list. + * This array is used only to look up the megasas_cmd given the context. The + * free commands themselves are maintained in a linked list called cmd_pool. + */ +static int megasas_alloc_cmds(struct megasas_instance *instance) +{ + int i; + int j; + u32 max_cmd; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * instance->cmd_list is an array of struct megasas_cmd pointers. + * Allocate the dynamic array first and then allocate individual + * commands. + */ + instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd, + GFP_KERNEL); + + if (!instance->cmd_list) { + printk(KERN_DEBUG "megasas: out of memory\n"); + return -ENOMEM; + } + + memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) * max_cmd); + + for (i = 0; i < max_cmd; i++) { + instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), + GFP_KERNEL); + + if (!instance->cmd_list[i]) { + + for (j = 0; j < i; j++) + kfree(instance->cmd_list[j]); + + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + return -ENOMEM; + } + } + + /* + * Add all the commands to command pool (instance->cmd_pool) + */ + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + memset(cmd, 0, sizeof(struct megasas_cmd)); + cmd->index = i; + cmd->instance = instance; + + list_add_tail(&cmd->list, &instance->cmd_pool); + } + + /* + * Create a frame pool and assign one frame to each cmd + */ + if (megasas_create_frame_pool(instance)) { + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + megasas_free_cmds(instance); + } + + return 0; +} + +/** + * megasas_get_controller_info - Returns FW's controller structure + * @instance: Adapter soft state + * @ctrl_info: Controller information structure + * + * Issues an internal command (DCMD) to get the FW's controller structure. + * This information is mainly used to find out the maximum IO transfer per + * command supported by the FW. + */ +static int +megasas_get_ctrl_info(struct megasas_instance *instance, + struct megasas_ctrl_info *ctrl_info) +{ + int ret = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_ctrl_info *ci; + dma_addr_t ci_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a free cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + ci = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_ctrl_info), &ci_h); + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); + dcmd->opcode = MR_DCMD_CTRL_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info); + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); + } else { + ret = -1; + } + + pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), + ci, ci_h); + + megasas_return_cmd(instance, cmd); + return ret; +} + +/** + * megasas_init_mfi - Initializes the FW + * @instance: Adapter soft state + * + * This is the main function for initializing MFI firmware. + */ +static int megasas_init_mfi(struct megasas_instance *instance) +{ + u32 context_sz; + u32 reply_q_sz; + u32 max_sectors_1; + u32 max_sectors_2; + struct megasas_register_set __iomem *reg_set; + + struct megasas_cmd *cmd; + struct megasas_ctrl_info *ctrl_info; + + struct megasas_init_frame *init_frame; + struct megasas_init_queue_info *initq_info; + dma_addr_t init_frame_h; + dma_addr_t initq_info_h; + + /* + * Map the message registers + */ + instance->base_addr = pci_resource_start(instance->pdev, 0); + + if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) { + printk(KERN_DEBUG "megasas: IO memory region busy!\n"); + return -EBUSY; + } + + instance->reg_set = ioremap_nocache(instance->base_addr, 8192); + + if (!instance->reg_set) { + printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); + goto fail_ioremap; + } + + reg_set = instance->reg_set; + + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance->reg_set)) + goto fail_ready_state; + + /* + * Get various operational parameters from status register + */ + instance->max_fw_cmds = readl(®_set->outbound_msg_0) & 0x00FFFF; + instance->max_num_sge = (readl(®_set->outbound_msg_0) & 0xFF0000) >> + 0x10; + /* + * Create a pool of commands + */ + if (megasas_alloc_cmds(instance)) + goto fail_alloc_cmds; + + /* + * Allocate memory for reply queue. Length of reply queue should + * be _one_ more than the maximum commands handled by the firmware. + * + * Note: When FW completes commands, it places corresponding contex + * values in this circular reply queue. This circular queue is a fairly + * typical producer-consumer queue. FW is the producer (of completed + * commands) and the driver is the consumer. + */ + context_sz = sizeof(u32); + reply_q_sz = context_sz * (instance->max_fw_cmds + 1); + + instance->reply_queue = pci_alloc_consistent(instance->pdev, + reply_q_sz, + &instance->reply_queue_h); + + if (!instance->reply_queue) { + printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n"); + goto fail_reply_queue; + } + + /* + * Prepare a init frame. Note the init frame points to queue info + * structure. Each frame has SGL allocated after first 64 bytes. For + * this frame - since we don't need any SGL - we use SGL's space as + * queue info structure + * + * We will not get a NULL command below. We just created the pool. + */ + cmd = megasas_get_cmd(instance); + + init_frame = (struct megasas_init_frame *)cmd->frame; + initq_info = (struct megasas_init_queue_info *) + ((unsigned long)init_frame + 64); + + init_frame_h = cmd->frame_phys_addr; + initq_info_h = init_frame_h + 64; + + memset(init_frame, 0, MEGAMFI_FRAME_SIZE); + memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); + + initq_info->reply_queue_entries = instance->max_fw_cmds + 1; + initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; + + initq_info->producer_index_phys_addr_lo = instance->producer_h; + initq_info->consumer_index_phys_addr_lo = instance->consumer_h; + + init_frame->cmd = MFI_CMD_INIT; + init_frame->cmd_status = 0xFF; + init_frame->queue_info_new_phys_addr_lo = initq_info_h; + + init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); + + /* + * Issue the init frame in polled mode + */ + if (megasas_issue_polled(instance, cmd)) { + printk(KERN_DEBUG "megasas: Failed to init firmware\n"); + goto fail_fw_init; + } + + megasas_return_cmd(instance, cmd); + + ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); + + /* + * Compute the max allowed sectors per IO: The controller info has two + * limits on max sectors. Driver should use the minimum of these two. + * + * 1 << stripe_sz_ops.min = max sectors per strip + * + * Note that older firmwares ( < FW ver 30) didn't report information + * to calculate max_sectors_1. So the number ended up as zero always. + */ + if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { + + max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * + ctrl_info->max_strips_per_io; + max_sectors_2 = ctrl_info->max_request_size; + + instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2) + ? max_sectors_1 : max_sectors_2; + } else + instance->max_sectors_per_req = instance->max_num_sge * + PAGE_SIZE / 512; + + kfree(ctrl_info); + + return 0; + + fail_fw_init: + megasas_return_cmd(instance, cmd); + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + fail_reply_queue: + megasas_free_cmds(instance); + + fail_alloc_cmds: + fail_ready_state: + iounmap(instance->reg_set); + + fail_ioremap: + pci_release_regions(instance->pdev); + + return -EINVAL; +} + +/** + * megasas_release_mfi - Reverses the FW initialization + * @intance: Adapter soft state + */ +static void megasas_release_mfi(struct megasas_instance *instance) +{ + u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + + megasas_free_cmds(instance); + + iounmap(instance->reg_set); + + pci_release_regions(instance->pdev); +} + +/** + * megasas_get_seq_num - Gets latest event sequence numbers + * @instance: Adapter soft state + * @eli: FW event log sequence numbers information + * + * FW maintains a log of all events in a non-volatile area. Upper layers would + * usually find out the latest sequence number of the events, the seq number at + * the boot etc. They would "read" all the events below the latest seq number + * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq + * number), they would subsribe to AEN (asynchronous event notification) and + * wait for the events to happen. + */ +static int +megasas_get_seq_num(struct megasas_instance *instance, + struct megasas_evt_log_info *eli) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_evt_log_info *el_info; + dma_addr_t el_info_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + el_info = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_evt_log_info), + &el_info_h); + + if (!el_info) { + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(el_info, 0, sizeof(*el_info)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); + dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = el_info_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info); + + megasas_issue_blocked_cmd(instance, cmd); + + /* + * Copy the data back into callers buffer + */ + memcpy(eli, el_info, sizeof(struct megasas_evt_log_info)); + + pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), + el_info, el_info_h); + + megasas_return_cmd(instance, cmd); + + return 0; +} + +/** + * megasas_register_aen - Registers for asynchronous event notification + * @instance: Adapter soft state + * @seq_num: The starting sequence number + * @class_locale: Class of the event + * + * This function subscribes for AEN for events beyond the @seq_num. It requests + * to be notified if and only if the event is of type @class_locale + */ +static int +megasas_register_aen(struct megasas_instance *instance, u32 seq_num, + u32 class_locale_word) +{ + int ret_val; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + union megasas_evt_class_locale curr_aen; + union megasas_evt_class_locale prev_aen; + + /* + * If there an AEN pending already (aen_cmd), check if the + * class_locale of that pending AEN is inclusive of the new + * AEN request we currently have. If it is, then we don't have + * to do anything. In other words, whichever events the current + * AEN request is subscribing to, have already been subscribed + * to. + * + * If the old_cmd is _not_ inclusive, then we have to abort + * that command, form a class_locale that is superset of both + * old and current and re-issue to the FW + */ + + curr_aen.word = class_locale_word; + + if (instance->aen_cmd) { + + prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1]; + + /* + * A class whose enum value is smaller is inclusive of all + * higher values. If a PROGRESS (= -1) was previously + * registered, then a new registration requests for higher + * classes need not be sent to FW. They are automatically + * included. + * + * Locale numbers don't have such hierarchy. They are bitmap + * values + */ + if ((prev_aen.members.class <= curr_aen.members.class) && + !((prev_aen.members.locale & curr_aen.members.locale) ^ + curr_aen.members.locale)) { + /* + * Previously issued event registration includes + * current request. Nothing to do. + */ + return 0; + } else { + curr_aen.members.locale |= prev_aen.members.locale; + + if (prev_aen.members.class < curr_aen.members.class) + curr_aen.members.class = prev_aen.members.class; + + instance->aen_cmd->abort_aen = 1; + ret_val = megasas_issue_blocked_abort_cmd(instance, + instance-> + aen_cmd); + + if (ret_val) { + printk(KERN_DEBUG "megasas: Failed to abort " + "previous AEN command\n"); + return ret_val; + } + } + } + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -ENOMEM; + + dcmd = &cmd->frame->dcmd; + + memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail)); + + /* + * Prepare DCMD for aen registration + */ + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); + dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; + dcmd->mbox.w[0] = seq_num; + dcmd->mbox.w[1] = curr_aen.word; + dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); + + /* + * Store reference to the cmd used to register for AEN. When an + * application wants us to register for AEN, we have to abort this + * cmd and re-register with a new EVENT LOCALE supplied by that app + */ + instance->aen_cmd = cmd; + + /* + * Issue the aen registration frame + */ + writel(cmd->frame_phys_addr >> 3, + &instance->reg_set->inbound_queue_port); + + return 0; +} + +/** + * megasas_start_aen - Subscribes to AEN during driver load time + * @instance: Adapter soft state + */ +static int megasas_start_aen(struct megasas_instance *instance) +{ + struct megasas_evt_log_info eli; + union megasas_evt_class_locale class_locale; + + /* + * Get the latest sequence number from FW + */ + memset(&eli, 0, sizeof(eli)); + + if (megasas_get_seq_num(instance, &eli)) + return -1; + + /* + * Register AEN with FW for latest sequence number plus 1 + */ + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + + return megasas_register_aen(instance, eli.newest_seq_num + 1, + class_locale.word); +} + +/** + * megasas_io_attach - Attaches this driver to SCSI mid-layer + * @instance: Adapter soft state + */ +static int megasas_io_attach(struct megasas_instance *instance) +{ + struct Scsi_Host *host = instance->host; + + /* + * Export parameters required by SCSI mid-layer + */ + host->irq = instance->pdev->irq; + host->unique_id = instance->unique_id; + host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS; + host->this_id = instance->init_id; + host->sg_tablesize = instance->max_num_sge; + host->max_sectors = instance->max_sectors_per_req; + host->cmd_per_lun = 128; + host->max_channel = MEGASAS_MAX_CHANNELS - 1; + host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; + host->max_lun = MEGASAS_MAX_LUN; + + /* + * Notify the mid-layer about the new controller + */ + if (scsi_add_host(host, &instance->pdev->dev)) { + printk(KERN_DEBUG "megasas: scsi_add_host failed\n"); + return -ENODEV; + } + + /* + * Trigger SCSI to scan our drives + */ + scsi_scan_host(host); + return 0; +} + +/** + * megasas_probe_one - PCI hotplug entry point + * @pdev: PCI device structure + * @id: PCI ids of supported hotplugged adapter + */ +static int __devinit +megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int rval; + struct Scsi_Host *host; + struct megasas_instance *instance; + + /* + * Announce PCI information + */ + printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device); + + printk("bus %d:slot %d:func %d\n", + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + /* + * PCI prepping: enable device set bus mastering and dma mask + */ + rval = pci_enable_device(pdev); + + if (rval) { + return rval; + } + + pci_set_master(pdev); + + /* + * All our contollers are capable of performing 64-bit DMA + */ + if (IS_DMA64) { + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) { + + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) + goto fail_set_dma_mask; + } + } else { + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) + goto fail_set_dma_mask; + } + + host = scsi_host_alloc(&megasas_template, + sizeof(struct megasas_instance)); + + if (!host) { + printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n"); + goto fail_alloc_instance; + } + + instance = (struct megasas_instance *)host->hostdata; + memset(instance, 0, sizeof(*instance)); + + instance->producer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->producer_h); + instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->consumer_h); + + if (!instance->producer || !instance->consumer) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "producer, consumer\n"); + goto fail_alloc_dma_buf; + } + + *instance->producer = 0; + *instance->consumer = 0; + + instance->evt_detail = pci_alloc_consistent(pdev, + sizeof(struct + megasas_evt_detail), + &instance->evt_detail_h); + + if (!instance->evt_detail) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "event detail structure\n"); + goto fail_alloc_dma_buf; + } + + /* + * Initialize locks and queues + */ + INIT_LIST_HEAD(&instance->cmd_pool); + + init_waitqueue_head(&instance->int_cmd_wait_q); + init_waitqueue_head(&instance->abort_cmd_wait_q); + + spin_lock_init(&instance->cmd_pool_lock); + spin_lock_init(&instance->instance_lock); + + sema_init(&instance->aen_mutex, 1); + sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); + + /* + * Initialize PCI related and misc parameters + */ + instance->pdev = pdev; + instance->host = host; + instance->unique_id = pdev->bus->number << 8 | pdev->devfn; + instance->init_id = MEGASAS_DEFAULT_INIT_ID; + + /* + * Initialize MFI Firmware + */ + if (megasas_init_mfi(instance)) + goto fail_init_mfi; + + /* + * Register IRQ + */ + if (request_irq(pdev->irq, megasas_isr, SA_SHIRQ, "megasas", instance)) { + printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); + goto fail_irq; + } + + megasas_enable_intr(instance->reg_set); + + /* + * Store instance in PCI softstate + */ + pci_set_drvdata(pdev, instance); + + /* + * Add this controller to megasas_mgmt_info structure so that it + * can be exported to management applications + */ + megasas_mgmt_info.count++; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance; + megasas_mgmt_info.max_index++; + + /* + * Initiate AEN (Asynchronous Event Notification) + */ + if (megasas_start_aen(instance)) { + printk(KERN_DEBUG "megasas: start aen failed\n"); + goto fail_start_aen; + } + + /* + * Register with SCSI mid-layer + */ + if (megasas_io_attach(instance)) + goto fail_io_attach; + + return 0; + + fail_start_aen: + fail_io_attach: + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; + megasas_mgmt_info.max_index--; + + pci_set_drvdata(pdev, NULL); + megasas_disable_intr(instance->reg_set); + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + fail_irq: + fail_init_mfi: + fail_alloc_dma_buf: + if (instance->evt_detail) + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + + if (instance->producer) + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + if (instance->consumer) + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + scsi_host_put(host); + + fail_alloc_instance: + fail_set_dma_mask: + pci_disable_device(pdev); + + return -ENODEV; +} + +/** + * megasas_flush_cache - Requests FW to flush all its caches + * @instance: Adapter soft state + */ +static void megasas_flush_cache(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; + dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; + + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +/** + * megasas_shutdown_controller - Instructs FW to shutdown the controller + * @instance: Adapter soft state + */ +static void megasas_shutdown_controller(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + if (instance->aen_cmd) + megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN; + + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +/** + * megasas_detach_one - PCI hot"un"plug entry point + * @pdev: PCI device structure + */ +static void megasas_detach_one(struct pci_dev *pdev) +{ + int i; + struct Scsi_Host *host; + struct megasas_instance *instance; + + instance = pci_get_drvdata(pdev); + host = instance->host; + + scsi_remove_host(instance->host); + megasas_flush_cache(instance); + megasas_shutdown_controller(instance); + + /* + * Take the instance off the instance array. Note that we will not + * decrement the max_index. We let this array be sparse array + */ + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + if (megasas_mgmt_info.instance[i] == instance) { + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[i] = NULL; + + break; + } + } + + pci_set_drvdata(instance->pdev, NULL); + + megasas_disable_intr(instance->reg_set); + + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, instance->evt_detail_h); + + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + + scsi_host_put(host); + + pci_set_drvdata(pdev, NULL); + + pci_disable_device(pdev); + + return; +} + +/** + * megasas_shutdown - Shutdown entry point + * @device: Generic device structure + */ +static void megasas_shutdown(struct pci_dev *pdev) +{ + struct megasas_instance *instance = pci_get_drvdata(pdev); + megasas_flush_cache(instance); +} + +/** + * megasas_mgmt_open - char node "open" entry point + */ +static int megasas_mgmt_open(struct inode *inode, struct file *filep) +{ + /* + * Allow only those users with admin rights + */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + return 0; +} + +/** + * megasas_mgmt_release - char node "release" entry point + */ +static int megasas_mgmt_release(struct inode *inode, struct file *filep) +{ + filep->private_data = NULL; + fasync_helper(-1, filep, 0, &megasas_async_queue); + + return 0; +} + +/** + * megasas_mgmt_fasync - Async notifier registration from applications + * + * This function adds the calling process to a driver global queue. When an + * event occurs, SIGIO will be sent to all processes in this queue. + */ +static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) +{ + int rc; + + down(&megasas_async_queue_mutex); + + rc = fasync_helper(fd, filep, mode, &megasas_async_queue); + + up(&megasas_async_queue_mutex); + + if (rc >= 0) { + /* For sanity check when we get ioctl */ + filep->private_data = filep; + return 0; + } + + printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc); + + return rc; +} + +/** + * megasas_mgmt_fw_ioctl - Issues management ioctls to FW + * @instance: Adapter soft state + * @argp: User's ioctl packet + */ +static int +megasas_mgmt_fw_ioctl(struct megasas_instance *instance, + struct megasas_iocpacket __user * user_ioc, + struct megasas_iocpacket *ioc) +{ + struct megasas_sge32 *kern_sge32; + struct megasas_cmd *cmd; + void *kbuff_arr[MAX_IOCTL_SGE]; + dma_addr_t buf_handle = 0; + int error = 0, i; + void *sense = NULL; + dma_addr_t sense_handle; + u32 *sense_ptr; + + memset(kbuff_arr, 0, sizeof(kbuff_arr)); + + if (ioc->sge_count > MAX_IOCTL_SGE) { + printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n", + ioc->sge_count, MAX_IOCTL_SGE); + return -EINVAL; + } + + cmd = megasas_get_cmd(instance); + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n"); + return -ENOMEM; + } + + /* + * User's IOCTL packet has 2 frames (maximum). Copy those two + * frames into our cmd's frames. cmd->frame's context will get + * overwritten when we copy from user's frames. So set that value + * alone separately + */ + memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); + cmd->frame->hdr.context = cmd->index; + + /* + * The management interface between applications and the fw uses + * MFI frames. E.g, RAID configuration changes, LD property changes + * etc are accomplishes through different kinds of MFI frames. The + * driver needs to care only about substituting user buffers with + * kernel buffers in SGLs. The location of SGL is embedded in the + * struct iocpacket itself. + */ + kern_sge32 = (struct megasas_sge32 *) + ((unsigned long)cmd->frame + ioc->sgl_off); + + /* + * For each user buffer, create a mirror buffer and copy in + */ + for (i = 0; i < ioc->sge_count; i++) { + kbuff_arr[i] = pci_alloc_consistent(instance->pdev, + ioc->sgl[i].iov_len, + &buf_handle); + if (!kbuff_arr[i]) { + printk(KERN_DEBUG "megasas: Failed to alloc " + "kernel SGL buffer for IOCTL \n"); + error = -ENOMEM; + goto out; + } + + /* + * We don't change the dma_coherent_mask, so + * pci_alloc_consistent only returns 32bit addresses + */ + kern_sge32[i].phys_addr = (u32) buf_handle; + kern_sge32[i].length = ioc->sgl[i].iov_len; + + /* + * We created a kernel buffer corresponding to the + * user buffer. Now copy in from the user buffer + */ + if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base, + (u32) (ioc->sgl[i].iov_len))) { + error = -EFAULT; + goto out; + } + } + + if (ioc->sense_len) { + sense = pci_alloc_consistent(instance->pdev, ioc->sense_len, + &sense_handle); + if (!sense) { + error = -ENOMEM; + goto out; + } + + sense_ptr = + (u32 *) ((unsigned long)cmd->frame + ioc->sense_off); + *sense_ptr = sense_handle; + } + + /* + * Set the sync_cmd flag so that the ISR knows not to complete this + * cmd to the SCSI mid-layer + */ + cmd->sync_cmd = 1; + megasas_issue_blocked_cmd(instance, cmd); + cmd->sync_cmd = 0; + + /* + * copy out the kernel buffers to user buffers + */ + for (i = 0; i < ioc->sge_count; i++) { + if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i], + ioc->sgl[i].iov_len)) { + error = -EFAULT; + goto out; + } + } + + /* + * copy out the sense + */ + if (ioc->sense_len) { + /* + * sense_ptr points to the location that has the user + * sense buffer address + */ + sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + + ioc->sense_off); + + if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), + sense, ioc->sense_len)) { + error = -EFAULT; + goto out; + } + } + + /* + * copy the status codes returned by the fw + */ + if (copy_to_user(&user_ioc->frame.hdr.cmd_status, + &cmd->frame->hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: Error copying out cmd_status\n"); + error = -EFAULT; + } + + out: + if (sense) { + pci_free_consistent(instance->pdev, ioc->sense_len, + sense, sense_handle); + } + + for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { + pci_free_consistent(instance->pdev, + kern_sge32[i].length, + kbuff_arr[i], kern_sge32[i].phys_addr); + } + + megasas_return_cmd(instance, cmd); + return error; +} + +static struct megasas_instance *megasas_lookup_instance(u16 host_no) +{ + int i; + + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + + if ((megasas_mgmt_info.instance[i]) && + (megasas_mgmt_info.instance[i]->host->host_no == host_no)) + return megasas_mgmt_info.instance[i]; + } + + return NULL; +} + +static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) +{ + struct megasas_iocpacket __user *user_ioc = + (struct megasas_iocpacket __user *)arg; + struct megasas_iocpacket *ioc; + struct megasas_instance *instance; + int error; + + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return -ENOMEM; + + if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { + error = -EFAULT; + goto out_kfree_ioc; + } + + instance = megasas_lookup_instance(ioc->host_no); + if (!instance) { + error = -ENODEV; + goto out_kfree_ioc; + } + + /* + * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds + */ + if (down_interruptible(&instance->ioctl_sem)) { + error = -ERESTARTSYS; + goto out_kfree_ioc; + } + error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); + up(&instance->ioctl_sem); + + out_kfree_ioc: + kfree(ioc); + return error; +} + +static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) +{ + struct megasas_instance *instance; + struct megasas_aen aen; + int error; + + if (file->private_data != file) { + printk(KERN_DEBUG "megasas: fasync_helper was not " + "called first\n"); + return -EINVAL; + } + + if (copy_from_user(&aen, (void __user *)arg, sizeof(aen))) + return -EFAULT; + + instance = megasas_lookup_instance(aen.host_no); + + if (!instance) + return -ENODEV; + + down(&instance->aen_mutex); + error = megasas_register_aen(instance, aen.seq_num, + aen.class_locale_word); + up(&instance->aen_mutex); + return error; +} + +/** + * megasas_mgmt_ioctl - char node ioctl entry point + */ +static long +megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE: + return megasas_mgmt_ioctl_fw(file, arg); + + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} + +#ifdef CONFIG_COMPAT +static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) +{ + struct compat_megasas_iocpacket __user *cioc = + (struct compat_megasas_iocpacket __user *)arg; + struct megasas_iocpacket __user *ioc = + compat_alloc_user_space(sizeof(struct megasas_iocpacket)); + int i; + int error = 0; + + clear_user(ioc, sizeof(*ioc)); + + if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || + copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || + copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || + copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || + copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || + copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) + return -EFAULT; + + for (i = 0; i < MAX_IOCTL_SGE; i++) { + compat_uptr_t ptr; + + if (get_user(ptr, &cioc->sgl[i].iov_base) || + put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || + copy_in_user(&ioc->sgl[i].iov_len, + &cioc->sgl[i].iov_len, sizeof(compat_size_t))) + return -EFAULT; + } + + error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); + + if (copy_in_user(&cioc->frame.hdr.cmd_status, + &ioc->frame.hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); + return -EFAULT; + } + return error; +} + +static long +megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE:{ + return megasas_mgmt_compat_ioctl_fw(file, arg); + } + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} +#endif + +/* + * File operations structure for management interface + */ +static struct file_operations megasas_mgmt_fops = { + .owner = THIS_MODULE, + .open = megasas_mgmt_open, + .release = megasas_mgmt_release, + .fasync = megasas_mgmt_fasync, + .unlocked_ioctl = megasas_mgmt_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = megasas_mgmt_compat_ioctl, +#endif +}; + +/* + * PCI hotplug support registration structure + */ +static struct pci_driver megasas_pci_driver = { + + .name = "megaraid_sas", + .id_table = megasas_pci_table, + .probe = megasas_probe_one, + .remove = __devexit_p(megasas_detach_one), + .shutdown = megasas_shutdown, +}; + +/* + * Sysfs driver attributes + */ +static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n", + MEGASAS_VERSION); +} + +static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL); + +static ssize_t +megasas_sysfs_show_release_date(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n", + MEGASAS_RELDATE); +} + +static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, + NULL); + +/** + * megasas_init - Driver load entry point + */ +static int __init megasas_init(void) +{ + int rval; + + /* + * Announce driver version and other information + */ + printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, + MEGASAS_EXT_VERSION); + + memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); + + /* + * Register character device node + */ + rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops); + + if (rval < 0) { + printk(KERN_DEBUG "megasas: failed to open device node\n"); + return rval; + } + + megasas_mgmt_majorno = rval; + + /* + * Register ourselves as PCI hotplug module + */ + rval = pci_module_init(&megasas_pci_driver); + + if (rval) { + printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); + } + + driver_create_file(&megasas_pci_driver.driver, &driver_attr_version); + driver_create_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + + return rval; +} + +/** + * megasas_exit - Driver unload entry point + */ +static void __exit megasas_exit(void) +{ + driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + + pci_unregister_driver(&megasas_pci_driver); + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); +} + +module_init(megasas_init); +module_exit(megasas_exit); diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h new file mode 100644 index 0000000..eaec9d5 --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -0,0 +1,1142 @@ +/* + * + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2003-2005 LSI Logic Corporation. + * + * 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. + * + * FILE : megaraid_sas.h + */ + +#ifndef LSI_MEGARAID_SAS_H +#define LSI_MEGARAID_SAS_H + +/** + * MegaRAID SAS Driver meta data + */ +#define MEGASAS_VERSION "00.00.02.00-rc4" +#define MEGASAS_RELDATE "Sep 16, 2005" +#define MEGASAS_EXT_VERSION "Fri Sep 16 12:37:08 EDT 2005" + +/* + * ===================================== + * MegaRAID SAS MFI firmware definitions + * ===================================== + */ + +/* + * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for + * protocol between the software and firmware. Commands are issued using + * "message frames" + */ + +/** + * FW posts its state in upper 4 bits of outbound_msg_0 register + */ +#define MFI_STATE_MASK 0xF0000000 +#define MFI_STATE_UNDEFINED 0x00000000 +#define MFI_STATE_BB_INIT 0x10000000 +#define MFI_STATE_FW_INIT 0x40000000 +#define MFI_STATE_WAIT_HANDSHAKE 0x60000000 +#define MFI_STATE_FW_INIT_2 0x70000000 +#define MFI_STATE_DEVICE_SCAN 0x80000000 +#define MFI_STATE_FLUSH_CACHE 0xA0000000 +#define MFI_STATE_READY 0xB0000000 +#define MFI_STATE_OPERATIONAL 0xC0000000 +#define MFI_STATE_FAULT 0xF0000000 + +#define MEGAMFI_FRAME_SIZE 64 + +/** + * During FW init, clear pending cmds & reset state using inbound_msg_0 + * + * ABORT : Abort all pending cmds + * READY : Move from OPERATIONAL to READY state; discard queue info + * MFIMODE : Discard (possible) low MFA posted in 64-bit mode (??) + * CLR_HANDSHAKE: FW is waiting for HANDSHAKE from BIOS or Driver + */ +#define MFI_INIT_ABORT 0x00000000 +#define MFI_INIT_READY 0x00000002 +#define MFI_INIT_MFIMODE 0x00000004 +#define MFI_INIT_CLEAR_HANDSHAKE 0x00000008 +#define MFI_RESET_FLAGS MFI_INIT_READY|MFI_INIT_MFIMODE + +/** + * MFI frame flags + */ +#define MFI_FRAME_POST_IN_REPLY_QUEUE 0x0000 +#define MFI_FRAME_DONT_POST_IN_REPLY_QUEUE 0x0001 +#define MFI_FRAME_SGL32 0x0000 +#define MFI_FRAME_SGL64 0x0002 +#define MFI_FRAME_SENSE32 0x0000 +#define MFI_FRAME_SENSE64 0x0004 +#define MFI_FRAME_DIR_NONE 0x0000 +#define MFI_FRAME_DIR_WRITE 0x0008 +#define MFI_FRAME_DIR_READ 0x0010 +#define MFI_FRAME_DIR_BOTH 0x0018 + +/** + * Definition for cmd_status + */ +#define MFI_CMD_STATUS_POLL_MODE 0xFF + +/** + * MFI command opcodes + */ +#define MFI_CMD_INIT 0x00 +#define MFI_CMD_LD_READ 0x01 +#define MFI_CMD_LD_WRITE 0x02 +#define MFI_CMD_LD_SCSI_IO 0x03 +#define MFI_CMD_PD_SCSI_IO 0x04 +#define MFI_CMD_DCMD 0x05 +#define MFI_CMD_ABORT 0x06 +#define MFI_CMD_SMP 0x07 +#define MFI_CMD_STP 0x08 + +#define MR_DCMD_CTRL_GET_INFO 0x01010000 + +#define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 +#define MR_FLUSH_CTRL_CACHE 0x01 +#define MR_FLUSH_DISK_CACHE 0x02 + +#define MR_DCMD_CTRL_SHUTDOWN 0x01050000 +#define MR_ENABLE_DRIVE_SPINDOWN 0x01 + +#define MR_DCMD_CTRL_EVENT_GET_INFO 0x01040100 +#define MR_DCMD_CTRL_EVENT_GET 0x01040300 +#define MR_DCMD_CTRL_EVENT_WAIT 0x01040500 +#define MR_DCMD_LD_GET_PROPERTIES 0x03030000 + +#define MR_DCMD_CLUSTER 0x08000000 +#define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 +#define MR_DCMD_CLUSTER_RESET_LD 0x08010200 + +/** + * MFI command completion codes + */ +enum MFI_STAT { + MFI_STAT_OK = 0x00, + MFI_STAT_INVALID_CMD = 0x01, + MFI_STAT_INVALID_DCMD = 0x02, + MFI_STAT_INVALID_PARAMETER = 0x03, + MFI_STAT_INVALID_SEQUENCE_NUMBER = 0x04, + MFI_STAT_ABORT_NOT_POSSIBLE = 0x05, + MFI_STAT_APP_HOST_CODE_NOT_FOUND = 0x06, + MFI_STAT_APP_IN_USE = 0x07, + MFI_STAT_APP_NOT_INITIALIZED = 0x08, + MFI_STAT_ARRAY_INDEX_INVALID = 0x09, + MFI_STAT_ARRAY_ROW_NOT_EMPTY = 0x0a, + MFI_STAT_CONFIG_RESOURCE_CONFLICT = 0x0b, + MFI_STAT_DEVICE_NOT_FOUND = 0x0c, + MFI_STAT_DRIVE_TOO_SMALL = 0x0d, + MFI_STAT_FLASH_ALLOC_FAIL = 0x0e, + MFI_STAT_FLASH_BUSY = 0x0f, + MFI_STAT_FLASH_ERROR = 0x10, + MFI_STAT_FLASH_IMAGE_BAD = 0x11, + MFI_STAT_FLASH_IMAGE_INCOMPLETE = 0x12, + MFI_STAT_FLASH_NOT_OPEN = 0x13, + MFI_STAT_FLASH_NOT_STARTED = 0x14, + MFI_STAT_FLUSH_FAILED = 0x15, + MFI_STAT_HOST_CODE_NOT_FOUNT = 0x16, + MFI_STAT_LD_CC_IN_PROGRESS = 0x17, + MFI_STAT_LD_INIT_IN_PROGRESS = 0x18, + MFI_STAT_LD_LBA_OUT_OF_RANGE = 0x19, + MFI_STAT_LD_MAX_CONFIGURED = 0x1a, + MFI_STAT_LD_NOT_OPTIMAL = 0x1b, + MFI_STAT_LD_RBLD_IN_PROGRESS = 0x1c, + MFI_STAT_LD_RECON_IN_PROGRESS = 0x1d, + MFI_STAT_LD_WRONG_RAID_LEVEL = 0x1e, + MFI_STAT_MAX_SPARES_EXCEEDED = 0x1f, + MFI_STAT_MEMORY_NOT_AVAILABLE = 0x20, + MFI_STAT_MFC_HW_ERROR = 0x21, + MFI_STAT_NO_HW_PRESENT = 0x22, + MFI_STAT_NOT_FOUND = 0x23, + MFI_STAT_NOT_IN_ENCL = 0x24, + MFI_STAT_PD_CLEAR_IN_PROGRESS = 0x25, + MFI_STAT_PD_TYPE_WRONG = 0x26, + MFI_STAT_PR_DISABLED = 0x27, + MFI_STAT_ROW_INDEX_INVALID = 0x28, + MFI_STAT_SAS_CONFIG_INVALID_ACTION = 0x29, + MFI_STAT_SAS_CONFIG_INVALID_DATA = 0x2a, + MFI_STAT_SAS_CONFIG_INVALID_PAGE = 0x2b, + MFI_STAT_SAS_CONFIG_INVALID_TYPE = 0x2c, + MFI_STAT_SCSI_DONE_WITH_ERROR = 0x2d, + MFI_STAT_SCSI_IO_FAILED = 0x2e, + MFI_STAT_SCSI_RESERVATION_CONFLICT = 0x2f, + MFI_STAT_SHUTDOWN_FAILED = 0x30, + MFI_STAT_TIME_NOT_SET = 0x31, + MFI_STAT_WRONG_STATE = 0x32, + MFI_STAT_LD_OFFLINE = 0x33, + MFI_STAT_PEER_NOTIFICATION_REJECTED = 0x34, + MFI_STAT_PEER_NOTIFICATION_FAILED = 0x35, + MFI_STAT_RESERVATION_IN_PROGRESS = 0x36, + MFI_STAT_I2C_ERRORS_DETECTED = 0x37, + MFI_STAT_PCI_ERRORS_DETECTED = 0x38, + + MFI_STAT_INVALID_STATUS = 0xFF +}; + +/* + * Number of mailbox bytes in DCMD message frame + */ +#define MFI_MBOX_SIZE 12 + +enum MR_EVT_CLASS { + + MR_EVT_CLASS_DEBUG = -2, + MR_EVT_CLASS_PROGRESS = -1, + MR_EVT_CLASS_INFO = 0, + MR_EVT_CLASS_WARNING = 1, + MR_EVT_CLASS_CRITICAL = 2, + MR_EVT_CLASS_FATAL = 3, + MR_EVT_CLASS_DEAD = 4, + +}; + +enum MR_EVT_LOCALE { + + MR_EVT_LOCALE_LD = 0x0001, + MR_EVT_LOCALE_PD = 0x0002, + MR_EVT_LOCALE_ENCL = 0x0004, + MR_EVT_LOCALE_BBU = 0x0008, + MR_EVT_LOCALE_SAS = 0x0010, + MR_EVT_LOCALE_CTRL = 0x0020, + MR_EVT_LOCALE_CONFIG = 0x0040, + MR_EVT_LOCALE_CLUSTER = 0x0080, + MR_EVT_LOCALE_ALL = 0xffff, + +}; + +enum MR_EVT_ARGS { + + MR_EVT_ARGS_NONE, + MR_EVT_ARGS_CDB_SENSE, + MR_EVT_ARGS_LD, + MR_EVT_ARGS_LD_COUNT, + MR_EVT_ARGS_LD_LBA, + MR_EVT_ARGS_LD_OWNER, + MR_EVT_ARGS_LD_LBA_PD_LBA, + MR_EVT_ARGS_LD_PROG, + MR_EVT_ARGS_LD_STATE, + MR_EVT_ARGS_LD_STRIP, + MR_EVT_ARGS_PD, + MR_EVT_ARGS_PD_ERR, + MR_EVT_ARGS_PD_LBA, + MR_EVT_ARGS_PD_LBA_LD, + MR_EVT_ARGS_PD_PROG, + MR_EVT_ARGS_PD_STATE, + MR_EVT_ARGS_PCI, + MR_EVT_ARGS_RATE, + MR_EVT_ARGS_STR, + MR_EVT_ARGS_TIME, + MR_EVT_ARGS_ECC, + +}; + +/* + * SAS controller properties + */ +struct megasas_ctrl_prop { + + u16 seq_num; + u16 pred_fail_poll_interval; + u16 intr_throttle_count; + u16 intr_throttle_timeouts; + u8 rebuild_rate; + u8 patrol_read_rate; + u8 bgi_rate; + u8 cc_rate; + u8 recon_rate; + u8 cache_flush_interval; + u8 spinup_drv_count; + u8 spinup_delay; + u8 cluster_enable; + u8 coercion_mode; + u8 alarm_enable; + u8 disable_auto_rebuild; + u8 disable_battery_warn; + u8 ecc_bucket_size; + u16 ecc_bucket_leak_rate; + u8 restore_hotspare_on_insertion; + u8 expose_encl_devices; + u8 reserved[38]; + +} __attribute__ ((packed)); + +/* + * SAS controller information + */ +struct megasas_ctrl_info { + + /* + * PCI device information + */ + struct { + + u16 vendor_id; + u16 device_id; + u16 sub_vendor_id; + u16 sub_device_id; + u8 reserved[24]; + + } __attribute__ ((packed)) pci; + + /* + * Host interface information + */ + struct { + + u8 PCIX:1; + u8 PCIE:1; + u8 iSCSI:1; + u8 SAS_3G:1; + u8 reserved_0:4; + u8 reserved_1[6]; + u8 port_count; + u64 port_addr[8]; + + } __attribute__ ((packed)) host_interface; + + /* + * Device (backend) interface information + */ + struct { + + u8 SPI:1; + u8 SAS_3G:1; + u8 SATA_1_5G:1; + u8 SATA_3G:1; + u8 reserved_0:4; + u8 reserved_1[6]; + u8 port_count; + u64 port_addr[8]; + + } __attribute__ ((packed)) device_interface; + + /* + * List of components residing in flash. All str are null terminated + */ + u32 image_check_word; + u32 image_component_count; + + struct { + + char name[8]; + char version[32]; + char build_date[16]; + char built_time[16]; + + } __attribute__ ((packed)) image_component[8]; + + /* + * List of flash components that have been flashed on the card, but + * are not in use, pending reset of the adapter. This list will be + * empty if a flash operation has not occurred. All stings are null + * terminated + */ + u32 pending_image_component_count; + + struct { + + char name[8]; + char version[32]; + char build_date[16]; + char build_time[16]; + + } __attribute__ ((packed)) pending_image_component[8]; + + u8 max_arms; + u8 max_spans; + u8 max_arrays; + u8 max_lds; + + char product_name[80]; + char serial_no[32]; + + /* + * Other physical/controller/operation information. Indicates the + * presence of the hardware + */ + struct { + + u32 bbu:1; + u32 alarm:1; + u32 nvram:1; + u32 uart:1; + u32 reserved:28; + + } __attribute__ ((packed)) hw_present; + + u32 current_fw_time; + + /* + * Maximum data transfer sizes + */ + u16 max_concurrent_cmds; + u16 max_sge_count; + u32 max_request_size; + + /* + * Logical and physical device counts + */ + u16 ld_present_count; + u16 ld_degraded_count; + u16 ld_offline_count; + + u16 pd_present_count; + u16 pd_disk_present_count; + u16 pd_disk_pred_failure_count; + u16 pd_disk_failed_count; + + /* + * Memory size information + */ + u16 nvram_size; + u16 memory_size; + u16 flash_size; + + /* + * Error counters + */ + u16 mem_correctable_error_count; + u16 mem_uncorrectable_error_count; + + /* + * Cluster information + */ + u8 cluster_permitted; + u8 cluster_active; + + /* + * Additional max data transfer sizes + */ + u16 max_strips_per_io; + + /* + * Controller capabilities structures + */ + struct { + + u32 raid_level_0:1; + u32 raid_level_1:1; + u32 raid_level_5:1; + u32 raid_level_1E:1; + u32 raid_level_6:1; + u32 reserved:27; + + } __attribute__ ((packed)) raid_levels; + + struct { + + u32 rbld_rate:1; + u32 cc_rate:1; + u32 bgi_rate:1; + u32 recon_rate:1; + u32 patrol_rate:1; + u32 alarm_control:1; + u32 cluster_supported:1; + u32 bbu:1; + u32 spanning_allowed:1; + u32 dedicated_hotspares:1; + u32 revertible_hotspares:1; + u32 foreign_config_import:1; + u32 self_diagnostic:1; + u32 mixed_redundancy_arr:1; + u32 global_hot_spares:1; + u32 reserved:17; + + } __attribute__ ((packed)) adapter_operations; + + struct { + + u32 read_policy:1; + u32 write_policy:1; + u32 io_policy:1; + u32 access_policy:1; + u32 disk_cache_policy:1; + u32 reserved:27; + + } __attribute__ ((packed)) ld_operations; + + struct { + + u8 min; + u8 max; + u8 reserved[2]; + + } __attribute__ ((packed)) stripe_sz_ops; + + struct { + + u32 force_online:1; + u32 force_offline:1; + u32 force_rebuild:1; + u32 reserved:29; + + } __attribute__ ((packed)) pd_operations; + + struct { + + u32 ctrl_supports_sas:1; + u32 ctrl_supports_sata:1; + u32 allow_mix_in_encl:1; + u32 allow_mix_in_ld:1; + u32 allow_sata_in_cluster:1; + u32 reserved:27; + + } __attribute__ ((packed)) pd_mix_support; + + /* + * Define ECC single-bit-error bucket information + */ + u8 ecc_bucket_count; + u8 reserved_2[11]; + + /* + * Include the controller properties (changeable items) + */ + struct megasas_ctrl_prop properties; + + /* + * Define FW pkg version (set in envt v'bles on OEM basis) + */ + char package_version[0x60]; + + u8 pad[0x800 - 0x6a0]; + +} __attribute__ ((packed)); + +/* + * =============================== + * MegaRAID SAS driver definitions + * =============================== + */ +#define MEGASAS_MAX_PD_CHANNELS 2 +#define MEGASAS_MAX_LD_CHANNELS 2 +#define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \ + MEGASAS_MAX_LD_CHANNELS) +#define MEGASAS_MAX_DEV_PER_CHANNEL 128 +#define MEGASAS_DEFAULT_INIT_ID -1 +#define MEGASAS_MAX_LUN 8 +#define MEGASAS_MAX_LD 64 + +/* + * When SCSI mid-layer calls driver's reset routine, driver waits for + * MEGASAS_RESET_WAIT_TIME seconds for all outstanding IO to complete. Note + * that the driver cannot _actually_ abort or reset pending commands. While + * it is waiting for the commands to complete, it prints a diagnostic message + * every MEGASAS_RESET_NOTICE_INTERVAL seconds + */ +#define MEGASAS_RESET_WAIT_TIME 180 +#define MEGASAS_RESET_NOTICE_INTERVAL 5 + +#define MEGASAS_IOCTL_CMD 0 + +/* + * FW reports the maximum of number of commands that it can accept (maximum + * commands that can be outstanding) at any time. The driver must report a + * lower number to the mid layer because it can issue a few internal commands + * itself (E.g, AEN, abort cmd, IOCTLs etc). The number of commands it needs + * is shown below + */ +#define MEGASAS_INT_CMDS 32 + +/* + * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit + * SGLs based on the size of dma_addr_t + */ +#define IS_DMA64 (sizeof(dma_addr_t) == 8) + +#define MFI_OB_INTR_STATUS_MASK 0x00000002 +#define MFI_POLL_TIMEOUT_SECS 10 + +struct megasas_register_set { + + u32 reserved_0[4]; /*0000h */ + + u32 inbound_msg_0; /*0010h */ + u32 inbound_msg_1; /*0014h */ + u32 outbound_msg_0; /*0018h */ + u32 outbound_msg_1; /*001Ch */ + + u32 inbound_doorbell; /*0020h */ + u32 inbound_intr_status; /*0024h */ + u32 inbound_intr_mask; /*0028h */ + + u32 outbound_doorbell; /*002Ch */ + u32 outbound_intr_status; /*0030h */ + u32 outbound_intr_mask; /*0034h */ + + u32 reserved_1[2]; /*0038h */ + + u32 inbound_queue_port; /*0040h */ + u32 outbound_queue_port; /*0044h */ + + u32 reserved_2; /*004Ch */ + + u32 index_registers[1004]; /*0050h */ + +} __attribute__ ((packed)); + +struct megasas_sge32 { + + u32 phys_addr; + u32 length; + +} __attribute__ ((packed)); + +struct megasas_sge64 { + + u64 phys_addr; + u32 length; + +} __attribute__ ((packed)); + +union megasas_sgl { + + struct megasas_sge32 sge32[1]; + struct megasas_sge64 sge64[1]; + +} __attribute__ ((packed)); + +struct megasas_header { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 lun; /*05h */ + u8 cdb_len; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 data_xferlen; /*14h */ + +} __attribute__ ((packed)); + +union megasas_sgl_frame { + + struct megasas_sge32 sge32[8]; + struct megasas_sge64 sge64[5]; + +} __attribute__ ((packed)); + +struct megasas_init_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + + u8 reserved_1; /*03h */ + u32 reserved_2; /*04h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 reserved_3; /*12h */ + u32 data_xfer_len; /*14h */ + + u32 queue_info_new_phys_addr_lo; /*18h */ + u32 queue_info_new_phys_addr_hi; /*1Ch */ + u32 queue_info_old_phys_addr_lo; /*20h */ + u32 queue_info_old_phys_addr_hi; /*24h */ + + u32 reserved_4[6]; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_init_queue_info { + + u32 init_flags; /*00h */ + u32 reply_queue_entries; /*04h */ + + u32 reply_queue_start_phys_addr_lo; /*08h */ + u32 reply_queue_start_phys_addr_hi; /*0Ch */ + u32 producer_index_phys_addr_lo; /*10h */ + u32 producer_index_phys_addr_hi; /*14h */ + u32 consumer_index_phys_addr_lo; /*18h */ + u32 consumer_index_phys_addr_hi; /*1Ch */ + +} __attribute__ ((packed)); + +struct megasas_io_frame { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 access_byte; /*05h */ + u8 reserved_0; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 lba_count; /*14h */ + + u32 sense_buf_phys_addr_lo; /*18h */ + u32 sense_buf_phys_addr_hi; /*1Ch */ + + u32 start_lba_lo; /*20h */ + u32 start_lba_hi; /*24h */ + + union megasas_sgl sgl; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_pthru_frame { + + u8 cmd; /*00h */ + u8 sense_len; /*01h */ + u8 cmd_status; /*02h */ + u8 scsi_status; /*03h */ + + u8 target_id; /*04h */ + u8 lun; /*05h */ + u8 cdb_len; /*06h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + u32 data_xfer_len; /*14h */ + + u32 sense_buf_phys_addr_lo; /*18h */ + u32 sense_buf_phys_addr_hi; /*1Ch */ + + u8 cdb[16]; /*20h */ + union megasas_sgl sgl; /*30h */ + +} __attribute__ ((packed)); + +struct megasas_dcmd_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + u8 reserved_1[4]; /*03h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + u32 opcode; /*18h */ + + union { /*1Ch */ + u8 b[12]; + u16 s[6]; + u32 w[3]; + } mbox; + + union megasas_sgl sgl; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_abort_frame { + + u8 cmd; /*00h */ + u8 reserved_0; /*01h */ + u8 cmd_status; /*02h */ + + u8 reserved_1; /*03h */ + u32 reserved_2; /*04h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 reserved_3; /*12h */ + u32 reserved_4; /*14h */ + + u32 abort_context; /*18h */ + u32 pad_1; /*1Ch */ + + u32 abort_mfi_phys_addr_lo; /*20h */ + u32 abort_mfi_phys_addr_hi; /*24h */ + + u32 reserved_5[6]; /*28h */ + +} __attribute__ ((packed)); + +struct megasas_smp_frame { + + u8 cmd; /*00h */ + u8 reserved_1; /*01h */ + u8 cmd_status; /*02h */ + u8 connection_status; /*03h */ + + u8 reserved_2[3]; /*04h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + u64 sas_addr; /*18h */ + + union { + struct megasas_sge32 sge32[2]; /* [0]: resp [1]: req */ + struct megasas_sge64 sge64[2]; /* [0]: resp [1]: req */ + } sgl; + +} __attribute__ ((packed)); + +struct megasas_stp_frame { + + u8 cmd; /*00h */ + u8 reserved_1; /*01h */ + u8 cmd_status; /*02h */ + u8 reserved_2; /*03h */ + + u8 target_id; /*04h */ + u8 reserved_3[2]; /*05h */ + u8 sge_count; /*07h */ + + u32 context; /*08h */ + u32 pad_0; /*0Ch */ + + u16 flags; /*10h */ + u16 timeout; /*12h */ + + u32 data_xfer_len; /*14h */ + + u16 fis[10]; /*18h */ + u32 stp_flags; + + union { + struct megasas_sge32 sge32[2]; /* [0]: resp [1]: data */ + struct megasas_sge64 sge64[2]; /* [0]: resp [1]: data */ + } sgl; + +} __attribute__ ((packed)); + +union megasas_frame { + + struct megasas_header hdr; + struct megasas_init_frame init; + struct megasas_io_frame io; + struct megasas_pthru_frame pthru; + struct megasas_dcmd_frame dcmd; + struct megasas_abort_frame abort; + struct megasas_smp_frame smp; + struct megasas_stp_frame stp; + + u8 raw_bytes[64]; +}; + +struct megasas_cmd; + +union megasas_evt_class_locale { + + struct { + u16 locale; + u8 reserved; + s8 class; + } __attribute__ ((packed)) members; + + u32 word; + +} __attribute__ ((packed)); + +struct megasas_evt_log_info { + u32 newest_seq_num; + u32 oldest_seq_num; + u32 clear_seq_num; + u32 shutdown_seq_num; + u32 boot_seq_num; + +} __attribute__ ((packed)); + +struct megasas_progress { + + u16 progress; + u16 elapsed_seconds; + +} __attribute__ ((packed)); + +struct megasas_evtarg_ld { + + u16 target_id; + u8 ld_index; + u8 reserved; + +} __attribute__ ((packed)); + +struct megasas_evtarg_pd { + u16 device_id; + u8 encl_index; + u8 slot_number; + +} __attribute__ ((packed)); + +struct megasas_evt_detail { + + u32 seq_num; + u32 time_stamp; + u32 code; + union megasas_evt_class_locale cl; + u8 arg_type; + u8 reserved1[15]; + + union { + struct { + struct megasas_evtarg_pd pd; + u8 cdb_length; + u8 sense_length; + u8 reserved[2]; + u8 cdb[16]; + u8 sense[64]; + } __attribute__ ((packed)) cdbSense; + + struct megasas_evtarg_ld ld; + + struct { + struct megasas_evtarg_ld ld; + u64 count; + } __attribute__ ((packed)) ld_count; + + struct { + u64 lba; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) ld_lba; + + struct { + struct megasas_evtarg_ld ld; + u32 prevOwner; + u32 newOwner; + } __attribute__ ((packed)) ld_owner; + + struct { + u64 ld_lba; + u64 pd_lba; + struct megasas_evtarg_ld ld; + struct megasas_evtarg_pd pd; + } __attribute__ ((packed)) ld_lba_pd_lba; + + struct { + struct megasas_evtarg_ld ld; + struct megasas_progress prog; + } __attribute__ ((packed)) ld_prog; + + struct { + struct megasas_evtarg_ld ld; + u32 prev_state; + u32 new_state; + } __attribute__ ((packed)) ld_state; + + struct { + u64 strip; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) ld_strip; + + struct megasas_evtarg_pd pd; + + struct { + struct megasas_evtarg_pd pd; + u32 err; + } __attribute__ ((packed)) pd_err; + + struct { + u64 lba; + struct megasas_evtarg_pd pd; + } __attribute__ ((packed)) pd_lba; + + struct { + u64 lba; + struct megasas_evtarg_pd pd; + struct megasas_evtarg_ld ld; + } __attribute__ ((packed)) pd_lba_ld; + + struct { + struct megasas_evtarg_pd pd; + struct megasas_progress prog; + } __attribute__ ((packed)) pd_prog; + + struct { + struct megasas_evtarg_pd pd; + u32 prevState; + u32 newState; + } __attribute__ ((packed)) pd_state; + + struct { + u16 vendorId; + u16 deviceId; + u16 subVendorId; + u16 subDeviceId; + } __attribute__ ((packed)) pci; + + u32 rate; + char str[96]; + + struct { + u32 rtc; + u32 elapsedSeconds; + } __attribute__ ((packed)) time; + + struct { + u32 ecar; + u32 elog; + char str[64]; + } __attribute__ ((packed)) ecc; + + u8 b[96]; + u16 s[48]; + u32 w[24]; + u64 d[12]; + } args; + + char description[128]; + +} __attribute__ ((packed)); + +struct megasas_instance { + + u32 *producer; + dma_addr_t producer_h; + u32 *consumer; + dma_addr_t consumer_h; + + u32 *reply_queue; + dma_addr_t reply_queue_h; + + unsigned long base_addr; + struct megasas_register_set __iomem *reg_set; + + s8 init_id; + u8 reserved[3]; + + u16 max_num_sge; + u16 max_fw_cmds; + u32 max_sectors_per_req; + + struct megasas_cmd **cmd_list; + struct list_head cmd_pool; + spinlock_t cmd_pool_lock; + struct dma_pool *frame_dma_pool; + struct dma_pool *sense_dma_pool; + + struct megasas_evt_detail *evt_detail; + dma_addr_t evt_detail_h; + struct megasas_cmd *aen_cmd; + struct semaphore aen_mutex; + struct semaphore ioctl_sem; + + struct Scsi_Host *host; + + wait_queue_head_t int_cmd_wait_q; + wait_queue_head_t abort_cmd_wait_q; + + struct pci_dev *pdev; + u32 unique_id; + + u32 fw_outstanding; + u32 hw_crit_error; + spinlock_t instance_lock; +}; + +#define MEGASAS_IS_LOGICAL(scp) \ + (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 + +#define MEGASAS_DEV_INDEX(inst, scp) \ + ((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ + scp->device->id + +struct megasas_cmd { + + union megasas_frame *frame; + dma_addr_t frame_phys_addr; + u8 *sense; + dma_addr_t sense_phys_addr; + + u32 index; + u8 sync_cmd; + u8 cmd_status; + u16 abort_aen; + + struct list_head list; + struct scsi_cmnd *scmd; + struct megasas_instance *instance; + u32 frame_count; +}; + +#define MAX_MGMT_ADAPTERS 1024 +#define MAX_IOCTL_SGE 16 + +struct megasas_iocpacket { + + u16 host_no; + u16 __pad1; + u32 sgl_off; + u32 sge_count; + u32 sense_off; + u32 sense_len; + union { + u8 raw[128]; + struct megasas_header hdr; + } frame; + + struct iovec sgl[MAX_IOCTL_SGE]; + +} __attribute__ ((packed)); + +struct megasas_aen { + u16 host_no; + u16 __pad1; + u32 seq_num; + u32 class_locale_word; +} __attribute__ ((packed)); + +#ifdef CONFIG_COMPAT +struct compat_megasas_iocpacket { + u16 host_no; + u16 __pad1; + u32 sgl_off; + u32 sge_count; + u32 sense_off; + u32 sense_len; + union { + u8 raw[128]; + struct megasas_header hdr; + } frame; + struct compat_iovec sgl[MAX_IOCTL_SGE]; +} __attribute__ ((packed)); + +#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct compat_megasas_iocpacket) +#else +#define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket) +#endif + +#define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen) + +struct megasas_mgmt_info { + + u16 count; + struct megasas_instance *instance[MAX_MGMT_ADAPTERS]; + int max_index; +}; + +#endif /*LSI_MEGARAID_SAS_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c49d28e..20fb798 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -185,6 +185,7 @@ #define PCI_DEVICE_ID_LSI_61C102 0x0901 #define PCI_DEVICE_ID_LSI_63C815 0x1000 #define PCI_DEVICE_ID_LSI_SAS1064 0x0050 +#define PCI_DEVICE_ID_LSI_SAS1064R 0x0411 #define PCI_DEVICE_ID_LSI_SAS1066 0x005E #define PCI_DEVICE_ID_LSI_SAS1068 0x0054 #define PCI_DEVICE_ID_LSI_SAS1064A 0x005C @@ -559,6 +560,7 @@ #define PCI_VENDOR_ID_DELL 0x1028 #define PCI_DEVICE_ID_DELL_RACIII 0x0008 #define PCI_DEVICE_ID_DELL_RAC4 0x0012 +#define PCI_DEVICE_ID_DELL_PERC5 0x0015 #define PCI_VENDOR_ID_MATROX 0x102B #define PCI_DEVICE_ID_MATROX_MGA_2 0x0518 -- cgit v0.10.2 From 7a8cf29d69e077dfe90e327859201fd9b75a47ce Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 22 Sep 2005 09:15:24 -0700 Subject: [SCSI] aacraid: Greater than 2TB capacity support Received from Mark Salyzyn from Adaptec. There are a few adapters that are capable of creating devices with this large of a capacity, but now that we have the large fib support in, the management applications will be capable of generating them. The problem is, once they are created, the driver will not be able to access the devices correctly without this patch. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index a8e3dfc..0a209b2 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -313,18 +313,37 @@ int aac_get_containers(struct aac_dev *dev) } dresp = (struct aac_mount *)fib_data(fibptr); + if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(index); + dinfo->type = cpu_to_le32(FT_FILESYS); + + if (fib_send(ContainerCommand, + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 1, 1, + NULL, NULL) < 0) + continue; + } else + dresp->mnt[0].capacityhigh = 0; + dprintk ((KERN_DEBUG - "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%u\n", + "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n", (int)index, (int)le32_to_cpu(dresp->status), (int)le32_to_cpu(dresp->mnt[0].vol), (int)le32_to_cpu(dresp->mnt[0].state), - (unsigned)le32_to_cpu(dresp->mnt[0].capacity))); + ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32))); if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr[index].valid = 1; fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[index].size = le32_to_cpu(dresp->mnt[0].capacity); + fsa_dev_ptr[index].size + = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) fsa_dev_ptr[index].ro = 1; } @@ -497,11 +516,29 @@ static int probe_container(struct aac_dev *dev, int cid) dresp = (struct aac_mount *) fib_data(fibptr); if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(cid); + dinfo->type = cpu_to_le32(FT_FILESYS); + + if (fib_send(ContainerCommand, + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 1, 1, + NULL, NULL) < 0) + goto error; + } else + dresp->mnt[0].capacityhigh = 0; + + if ((le32_to_cpu(dresp->status) == ST_OK) && (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr[cid].valid = 1; fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[cid].size = le32_to_cpu(dresp->mnt[0].capacity); + fsa_dev_ptr[cid].size + = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) fsa_dev_ptr[cid].ro = 1; } @@ -854,7 +891,40 @@ static void io_callback(void *context, struct fib * fibptr) dev = (struct aac_dev *)scsicmd->device->host->hostdata; cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); - dprintk((KERN_DEBUG "io_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3], jiffies)); + if (nblank(dprintk(x))) { + u64 lba; + switch (scsicmd->cmnd[0]) { + case WRITE_6: + case READ_6: + lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | + (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; + break; + case WRITE_16: + case READ_16: + lba = ((u64)scsicmd->cmnd[2] << 56) | + ((u64)scsicmd->cmnd[3] << 48) | + ((u64)scsicmd->cmnd[4] << 40) | + ((u64)scsicmd->cmnd[5] << 32) | + ((u64)scsicmd->cmnd[6] << 24) | + (scsicmd->cmnd[7] << 16) | + (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; + break; + case WRITE_12: + case READ_12: + lba = ((u64)scsicmd->cmnd[2] << 24) | + (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + break; + default: + lba = ((u64)scsicmd->cmnd[2] << 24) | + (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + break; + } + printk(KERN_DEBUG + "io_callback[cpu %d]: lba = %llu, t = %ld.\n", + smp_processor_id(), (unsigned long long)lba, jiffies); + } if (fibptr == NULL) BUG(); @@ -895,7 +965,7 @@ static void io_callback(void *context, struct fib * fibptr) static int aac_read(struct scsi_cmnd * scsicmd, int cid) { - u32 lba; + u64 lba; u32 count; int status; @@ -907,23 +977,69 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) /* * Get block address and transfer length */ - if (scsicmd->cmnd[0] == READ_6) /* 6 byte command */ - { + switch (scsicmd->cmnd[0]) { + case READ_6: dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid)); - lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; + lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | + (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; count = scsicmd->cmnd[4]; if (count == 0) count = 256; - } else { + break; + case READ_16: + dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid)); + + lba = ((u64)scsicmd->cmnd[2] << 56) | + ((u64)scsicmd->cmnd[3] << 48) | + ((u64)scsicmd->cmnd[4] << 40) | + ((u64)scsicmd->cmnd[5] << 32) | + ((u64)scsicmd->cmnd[6] << 24) | + (scsicmd->cmnd[7] << 16) | + (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; + count = (scsicmd->cmnd[10] << 24) | + (scsicmd->cmnd[11] << 16) | + (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; + break; + case READ_12: + dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid)); + + lba = ((u64)scsicmd->cmnd[2] << 24) | + (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + count = (scsicmd->cmnd[6] << 24) | + (scsicmd->cmnd[7] << 16) | + (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; + break; + default: dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid)); - lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + lba = ((u64)scsicmd->cmnd[2] << 24) | + (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; + break; } - dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", + dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); + if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) && + (lba & 0xffffffff00000000LL)) { + dprintk((KERN_DEBUG "aac_read: Illegal lba\n")); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, + HARDWARE_ERROR, + SENCODE_INTERNAL_TARGET_FAILURE, + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, + 0, 0); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + scsicmd->scsi_done(scsicmd); + return 0; + } /* * Alocate and initialize a Fib */ @@ -936,8 +1052,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) if (dev->raw_io_interface) { struct aac_raw_io *readcmd; readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - readcmd->block[0] = cpu_to_le32(lba); - readcmd->block[1] = 0; + readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); readcmd->count = cpu_to_le32(count<<9); readcmd->cid = cpu_to_le16(cid); readcmd->flags = cpu_to_le16(1); @@ -964,7 +1080,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) readcmd->command = cpu_to_le32(VM_CtHostRead64); readcmd->cid = cpu_to_le16(cid); readcmd->sector_count = cpu_to_le16(count); - readcmd->block = cpu_to_le32(lba); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); readcmd->pad = 0; readcmd->flags = 0; @@ -989,7 +1105,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) readcmd = (struct aac_read *) fib_data(cmd_fibcontext); readcmd->command = cpu_to_le32(VM_CtBlockRead); readcmd->cid = cpu_to_le32(cid); - readcmd->block = cpu_to_le32(lba); + readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); readcmd->count = cpu_to_le32(count * 512); aac_build_sg(scsicmd, &readcmd->sg); @@ -1031,7 +1147,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) static int aac_write(struct scsi_cmnd * scsicmd, int cid) { - u32 lba; + u64 lba; u32 count; int status; u16 fibsize; @@ -1048,13 +1164,48 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) count = scsicmd->cmnd[4]; if (count == 0) count = 256; + } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ + dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid)); + + lba = ((u64)scsicmd->cmnd[2] << 56) | + ((u64)scsicmd->cmnd[3] << 48) | + ((u64)scsicmd->cmnd[4] << 40) | + ((u64)scsicmd->cmnd[5] << 32) | + ((u64)scsicmd->cmnd[6] << 24) | + (scsicmd->cmnd[7] << 16) | + (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; + count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | + (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; + } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ + dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid)); + + lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) + | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) + | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; } else { dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid)); - lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } - dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", + dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", smp_processor_id(), (unsigned long long)lba, jiffies)); + if ((!(dev->raw_io_interface) || !(dev->raw_io_64)) + && (lba & 0xffffffff00000000LL)) { + dprintk((KERN_DEBUG "aac_write: Illegal lba\n")); + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, + HARDWARE_ERROR, + SENCODE_INTERNAL_TARGET_FAILURE, + ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, + 0, 0); + memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + scsicmd->scsi_done(scsicmd); + return 0; + } /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -1068,8 +1219,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) if (dev->raw_io_interface) { struct aac_raw_io *writecmd; writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); - writecmd->block[0] = cpu_to_le32(lba); - writecmd->block[1] = 0; + writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); + writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); writecmd->count = cpu_to_le32(count<<9); writecmd->cid = cpu_to_le16(cid); writecmd->flags = 0; @@ -1096,7 +1247,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) writecmd->command = cpu_to_le32(VM_CtHostWrite64); writecmd->cid = cpu_to_le16(cid); writecmd->sector_count = cpu_to_le16(count); - writecmd->block = cpu_to_le32(lba); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); writecmd->pad = 0; writecmd->flags = 0; @@ -1121,7 +1272,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) writecmd = (struct aac_write *) fib_data(cmd_fibcontext); writecmd->command = cpu_to_le32(VM_CtBlockWrite); writecmd->cid = cpu_to_le32(cid); - writecmd->block = cpu_to_le32(lba); + writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); writecmd->count = cpu_to_le32(count * 512); writecmd->sg.count = cpu_to_le32(1); /* ->stable is not used - it did mean which type of write */ @@ -1310,6 +1461,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) */ if ((fsa_dev_ptr[cid].valid & 1) == 0) { switch (scsicmd->cmnd[0]) { + case SERVICE_ACTION_IN: + if (!(dev->raw_io_interface) || + !(dev->raw_io_64) || + ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) + break; case INQUIRY: case READ_CAPACITY: case TEST_UNIT_READY: @@ -1375,7 +1531,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) memset(&inq_data, 0, sizeof (struct inquiry_data)); inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ - inq_data.inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data.inqd_len = 31; /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ @@ -1397,13 +1552,55 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); return aac_get_container_name(scsicmd, cid); } + case SERVICE_ACTION_IN: + if (!(dev->raw_io_interface) || + !(dev->raw_io_64) || + ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) + break; + { + u64 capacity; + char cp[12]; + unsigned int offset = 0; + + dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n")); + capacity = fsa_dev_ptr[cid].size - 1; + if (scsicmd->cmnd[13] > 12) { + offset = scsicmd->cmnd[13] - 12; + if (offset > sizeof(cp)) + break; + memset(cp, 0, offset); + aac_internal_transfer(scsicmd, cp, 0, offset); + } + cp[0] = (capacity >> 56) & 0xff; + cp[1] = (capacity >> 48) & 0xff; + cp[2] = (capacity >> 40) & 0xff; + cp[3] = (capacity >> 32) & 0xff; + cp[4] = (capacity >> 24) & 0xff; + cp[5] = (capacity >> 16) & 0xff; + cp[6] = (capacity >> 8) & 0xff; + cp[7] = (capacity >> 0) & 0xff; + cp[8] = 0; + cp[9] = 0; + cp[10] = 2; + cp[11] = 0; + aac_internal_transfer(scsicmd, cp, offset, sizeof(cp)); + + /* Do not cache partition table for arrays */ + scsicmd->device->removable = 1; + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + scsicmd->scsi_done(scsicmd); + + return 0; + } + case READ_CAPACITY: { u32 capacity; char cp[8]; dprintk((KERN_DEBUG "READ CAPACITY command.\n")); - if (fsa_dev_ptr[cid].size <= 0x100000000LL) + if (fsa_dev_ptr[cid].size <= 0x100000000ULL) capacity = fsa_dev_ptr[cid].size - 1; else capacity = (u32)-1; @@ -1417,6 +1614,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) cp[6] = 2; cp[7] = 0; aac_internal_transfer(scsicmd, cp, 0, sizeof(cp)); + /* Do not cache partition table for arrays */ + scsicmd->device->removable = 1; scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; scsicmd->scsi_done(scsicmd); @@ -1497,6 +1696,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) { case READ_6: case READ_10: + case READ_12: + case READ_16: /* * Hack to keep track of ordinal number of the device that * corresponds to a container. Needed to convert @@ -1504,17 +1705,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) */ spin_unlock_irq(host->host_lock); - if (scsicmd->request->rq_disk) - memcpy(fsa_dev_ptr[cid].devname, - scsicmd->request->rq_disk->disk_name, - 8); - + if (scsicmd->request->rq_disk) + strlcpy(fsa_dev_ptr[cid].devname, + scsicmd->request->rq_disk->disk_name, + min(sizeof(fsa_dev_ptr[cid].devname), + sizeof(scsicmd->request->rq_disk->disk_name) + 1)); ret = aac_read(scsicmd, cid); spin_lock_irq(host->host_lock); return ret; case WRITE_6: case WRITE_10: + case WRITE_12: + case WRITE_16: spin_unlock_irq(host->host_lock); ret = aac_write(scsicmd, cid); spin_lock_irq(host->host_lock); @@ -1745,6 +1948,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr) case WRITE_10: case READ_12: case WRITE_12: + case READ_16: + case WRITE_16: if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) { printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); } else { @@ -1850,8 +2055,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr) sizeof(scsicmd->sense_buffer) : le32_to_cpu(srbreply->sense_data_size); #ifdef AAC_DETAILED_STATUS_INFO - dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", - le32_to_cpu(srbreply->status), len)); + printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", + le32_to_cpu(srbreply->status), len); #endif memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index e405281..6fd5074 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1,6 +1,10 @@ #if (!defined(dprintk)) # define dprintk(x) #endif +/* eg: if (nblank(dprintk(x))) */ +#define _nblank(x) #x +#define nblank(x) _nblank(x)[0] + /*------------------------------------------------------------------------------ * D E F I N E S @@ -1012,6 +1016,7 @@ struct aac_dev /* macro side-effects BEWARE */ # define raw_io_interface \ init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) + u8 raw_io_64; u8 printf_enabled; }; @@ -1362,8 +1367,10 @@ struct aac_srb_reply #define VM_CtBlockVerify64 18 #define VM_CtHostRead64 19 #define VM_CtHostWrite64 20 +#define VM_DrvErrTblLog 21 +#define VM_NameServe64 22 -#define MAX_VMCOMMAND_NUM 21 /* used for sizing stats array - leave last */ +#define MAX_VMCOMMAND_NUM 23 /* used for sizing stats array - leave last */ /* * Descriptive information (eg, vital stats) @@ -1472,6 +1479,7 @@ struct aac_mntent { manager (eg, filesystem) */ __le32 altoid; /* != oid <==> snapshot or broken mirror exists */ + __le32 capacityhigh; }; #define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */ diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 75abd04..7f11c85 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -315,6 +315,13 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) - sizeof(struct aac_fibhdr) - sizeof(struct aac_write) + sizeof(struct sgmap)) / sizeof(struct sgmap); + dev->raw_io_64 = 0; + if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, + 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && + (status[0] == 0x00000001)) { + if (status[1] & AAC_OPT_NEW_COMM_64) + dev->raw_io_64 = 1; + } if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, status+3, status+4)) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 4ff29d7..31d96b9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -772,6 +772,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, shost->irq = pdev->irq; shost->base = pci_resource_start(pdev, 0); shost->unique_id = unique_id; + shost->max_cmd_len = 16; aac = (struct aac_dev *)shost->hostdata; aac->scsi_host_ptr = shost; -- cgit v0.10.2 From 2f130980d14cb938226011875ca5224cd46dc1f9 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Mon, 26 Sep 2005 13:02:15 -0700 Subject: [SCSI] aacraid: aacraid: AIF preallocation (update) Recevied from Mark Salyzyn from Adaptec. Aif pre-allocation is used to pull the kmalloc outside of the locks. Applies to the scsi-misc-2.6 git tree. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index a1d303f0..3741be2 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -805,7 +805,6 @@ int aac_command_thread(struct aac_dev * dev) { struct hw_fib *hw_fib, *hw_newfib; struct fib *fib, *newfib; - struct aac_queue_block *queues = dev->queues; struct aac_fib_context *fibctx; unsigned long flags; DECLARE_WAITQUEUE(wait, current); @@ -825,21 +824,22 @@ int aac_command_thread(struct aac_dev * dev) * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; - add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); + add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); + dprintk ((KERN_INFO "aac_command_thread start\n")); while(1) { - spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { + spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); + while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { struct list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); - - entry = queues->queue[HostNormCmdQueue].cmdq.next; + + entry = dev->queues->queue[HostNormCmdQueue].cmdq.next; list_del(entry); - - spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); + + spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); fib = list_entry(entry, struct fib, fiblink); /* * We will process the FIB here or pass it to a @@ -869,9 +869,54 @@ int aac_command_thread(struct aac_dev * dev) u32 time_now, time_last; unsigned long flagv; + unsigned num; + struct hw_fib ** hw_fib_pool, ** hw_fib_p; + struct fib ** fib_pool, ** fib_p; time_now = jiffies/HZ; + /* + * Warning: no sleep allowed while + * holding spinlock. We take the estimate + * and pre-allocate a set of fibs outside the + * lock. + */ + num = le32_to_cpu(dev->init->AdapterFibsSize) + / sizeof(struct hw_fib); /* some extra */ + spin_lock_irqsave(&dev->fib_lock, flagv); + entry = dev->fib_list.next; + while (entry != &dev->fib_list) { + entry = entry->next; + ++num; + } + spin_unlock_irqrestore(&dev->fib_lock, flagv); + hw_fib_pool = NULL; + fib_pool = NULL; + if (num + && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL))) + && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) { + hw_fib_p = hw_fib_pool; + fib_p = fib_pool; + while (hw_fib_p < &hw_fib_pool[num]) { + if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) { + --hw_fib_p; + break; + } + if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) { + kfree(*(--hw_fib_p)); + break; + } + } + if ((num = hw_fib_p - hw_fib_pool) == 0) { + kfree(fib_pool); + fib_pool = NULL; + kfree(hw_fib_pool); + hw_fib_pool = NULL; + } + } else if (hw_fib_pool) { + kfree(hw_fib_pool); + hw_fib_pool = NULL; + } spin_lock_irqsave(&dev->fib_lock, flagv); entry = dev->fib_list.next; /* @@ -880,6 +925,8 @@ int aac_command_thread(struct aac_dev * dev) * fib, and then set the event to wake up the * thread that is waiting for it. */ + hw_fib_p = hw_fib_pool; + fib_p = fib_pool; while (entry != &dev->fib_list) { /* * Extract the fibctx @@ -912,9 +959,11 @@ int aac_command_thread(struct aac_dev * dev) * Warning: no sleep allowed while * holding spinlock */ - hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); - if (newfib && hw_newfib) { + if (hw_fib_p < &hw_fib_pool[num]) { + hw_newfib = *hw_fib_p; + *(hw_fib_p++) = NULL; + newfib = *fib_p; + *(fib_p++) = NULL; /* * Make the copy of the FIB */ @@ -929,15 +978,11 @@ int aac_command_thread(struct aac_dev * dev) fibctx->count++; /* * Set the event to wake up the - * thread that will waiting. + * thread that is waiting. */ up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); - if(newfib) - kfree(newfib); - if(hw_newfib) - kfree(hw_newfib); } entry = entry->next; } @@ -947,21 +992,38 @@ int aac_command_thread(struct aac_dev * dev) *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); + /* Free up the remaining resources */ + hw_fib_p = hw_fib_pool; + fib_p = fib_pool; + while (hw_fib_p < &hw_fib_pool[num]) { + if (*hw_fib_p) + kfree(*hw_fib_p); + if (*fib_p) + kfree(*fib_p); + ++fib_p; + ++hw_fib_p; + } + if (hw_fib_pool) + kfree(hw_fib_pool); + if (fib_pool) + kfree(fib_pool); } - spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); kfree(fib); + spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); } /* * There are no more AIF's */ - spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); + spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); schedule(); if(signal_pending(current)) break; set_current_state(TASK_INTERRUPTIBLE); } - remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); + if (dev->queues) + remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); dev->aif_thread = 0; complete_and_exit(&dev->aif_completion, 0); + return 0; } -- cgit v0.10.2 From 131256cf203d0df62014dda8453a70cb6af0d0bb Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Mon, 26 Sep 2005 13:04:56 -0700 Subject: [SCSI] aacraid: handle AIF hotplug events (update) Received from Mark Salyzyn from Adaptec. Hotplug sniffs the AIFs (events) from the adapter and if a container change resulting in the device going offline (container zero), online (container zero completed) or changing capacity (morph) it will take actions by calling the appropriate API. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0a209b2..85d133c 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -479,7 +479,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) * is updated in the struct fsa_dev_info structure rather than returned. */ -static int probe_container(struct aac_dev *dev, int cid) +int probe_container(struct aac_dev *dev, int cid) { struct fsa_dev_info *fsa_dev_ptr; int status; @@ -1471,6 +1471,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case TEST_UNIT_READY: spin_unlock_irq(host->host_lock); probe_container(dev, cid); + if ((fsa_dev_ptr[cid].valid & 1) == 0) + fsa_dev_ptr[cid].valid = 0; spin_lock_irq(host->host_lock); if (fsa_dev_ptr[cid].valid == 0) { scsicmd->result = DID_NO_CONNECT << 16; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 6fd5074..0880f48 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -780,7 +780,9 @@ struct fsa_dev_info { u64 last; u64 size; u32 type; + u32 config_waiting_on; u16 queue_depth; + u8 config_needed; u8 valid; u8 ro; u8 locked; @@ -1715,6 +1717,7 @@ extern struct aac_common aac_config; #define AifCmdJobProgress 2 /* Progress report */ #define AifJobCtrZero 101 /* Array Zero progress */ #define AifJobStsSuccess 1 /* Job completes */ +#define AifJobStsRunning 102 /* Job running */ #define AifCmdAPIReport 3 /* Report from other user of API */ #define AifCmdDriverNotify 4 /* Notify host driver of event */ #define AifDenMorphComplete 200 /* A morph operation completed */ @@ -1785,6 +1788,7 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size); struct aac_driver_ident* aac_get_driver_ident(int devtype); int aac_get_adapter_info(struct aac_dev* dev); int aac_send_shutdown(struct aac_dev *dev); +int probe_container(struct aac_dev *dev, int cid); extern int numacb; extern int acbsize; extern char aac_driver_version[]; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 3741be2..69985b08 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "aacraid.h" @@ -791,6 +792,268 @@ void aac_printf(struct aac_dev *dev, u32 val) memset(cp, 0, 256); } + +/** + * aac_handle_aif - Handle a message from the firmware + * @dev: Which adapter this fib is from + * @fibptr: Pointer to fibptr from adapter + * + * This routine handles a driver notify fib from the adapter and + * dispatches it to the appropriate routine for handling. + */ + +static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) +{ + struct hw_fib * hw_fib = fibptr->hw_fib; + struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; + int busy; + u32 container; + struct scsi_device *device; + enum { + NOTHING, + DELETE, + ADD, + CHANGE + } device_config_needed; + + /* Sniff for container changes */ + + if (!dev) + return; + container = (u32)-1; + + /* + * We have set this up to try and minimize the number of + * re-configures that take place. As a result of this when + * certain AIF's come in we will set a flag waiting for another + * type of AIF before setting the re-config flag. + */ + switch (le32_to_cpu(aifcmd->command)) { + case AifCmdDriverNotify: + switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) { + /* + * Morph or Expand complete + */ + case AifDenMorphComplete: + case AifDenVolumeExtendComplete: + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + if (container >= dev->maximum_num_containers) + break; + + /* + * Find the Scsi_Device associated with the SCSI + * address. Make sure we have the right array, and if + * so set the flag to initiate a new re-config once we + * see an AifEnConfigChange AIF come through. + */ + + if ((dev != NULL) && (dev->scsi_host_ptr != NULL)) { + device = scsi_device_lookup(dev->scsi_host_ptr, + CONTAINER_TO_CHANNEL(container), + CONTAINER_TO_ID(container), + CONTAINER_TO_LUN(container)); + if (device) { + dev->fsa_dev[container].config_needed = CHANGE; + dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; + scsi_device_put(device); + } + } + } + + /* + * If we are waiting on something and this happens to be + * that thing then set the re-configure flag. + */ + if (container != (u32)-1) { + if (container >= dev->maximum_num_containers) + break; + if (dev->fsa_dev[container].config_waiting_on == + le32_to_cpu(*(u32 *)aifcmd->data)) + dev->fsa_dev[container].config_waiting_on = 0; + } else for (container = 0; + container < dev->maximum_num_containers; ++container) { + if (dev->fsa_dev[container].config_waiting_on == + le32_to_cpu(*(u32 *)aifcmd->data)) + dev->fsa_dev[container].config_waiting_on = 0; + } + break; + + case AifCmdEventNotify: + switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) { + /* + * Add an Array. + */ + case AifEnAddContainer: + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + if (container >= dev->maximum_num_containers) + break; + dev->fsa_dev[container].config_needed = ADD; + dev->fsa_dev[container].config_waiting_on = + AifEnConfigChange; + break; + + /* + * Delete an Array. + */ + case AifEnDeleteContainer: + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + if (container >= dev->maximum_num_containers) + break; + dev->fsa_dev[container].config_needed = DELETE; + dev->fsa_dev[container].config_waiting_on = + AifEnConfigChange; + break; + + /* + * Container change detected. If we currently are not + * waiting on something else, setup to wait on a Config Change. + */ + case AifEnContainerChange: + container = le32_to_cpu(((u32 *)aifcmd->data)[1]); + if (container >= dev->maximum_num_containers) + break; + if (dev->fsa_dev[container].config_waiting_on) + break; + dev->fsa_dev[container].config_needed = CHANGE; + dev->fsa_dev[container].config_waiting_on = + AifEnConfigChange; + break; + + case AifEnConfigChange: + break; + + } + + /* + * If we are waiting on something and this happens to be + * that thing then set the re-configure flag. + */ + if (container != (u32)-1) { + if (container >= dev->maximum_num_containers) + break; + if (dev->fsa_dev[container].config_waiting_on == + le32_to_cpu(*(u32 *)aifcmd->data)) + dev->fsa_dev[container].config_waiting_on = 0; + } else for (container = 0; + container < dev->maximum_num_containers; ++container) { + if (dev->fsa_dev[container].config_waiting_on == + le32_to_cpu(*(u32 *)aifcmd->data)) + dev->fsa_dev[container].config_waiting_on = 0; + } + break; + + case AifCmdJobProgress: + /* + * These are job progress AIF's. When a Clear is being + * done on a container it is initially created then hidden from + * the OS. When the clear completes we don't get a config + * change so we monitor the job status complete on a clear then + * wait for a container change. + */ + + if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero)) + && ((((u32 *)aifcmd->data)[6] == ((u32 *)aifcmd->data)[5]) + || (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess)))) { + for (container = 0; + container < dev->maximum_num_containers; + ++container) { + /* + * Stomp on all config sequencing for all + * containers? + */ + dev->fsa_dev[container].config_waiting_on = + AifEnContainerChange; + dev->fsa_dev[container].config_needed = ADD; + } + } + if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero)) + && (((u32 *)aifcmd->data)[6] == 0) + && (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsRunning))) { + for (container = 0; + container < dev->maximum_num_containers; + ++container) { + /* + * Stomp on all config sequencing for all + * containers? + */ + dev->fsa_dev[container].config_waiting_on = + AifEnContainerChange; + dev->fsa_dev[container].config_needed = DELETE; + } + } + break; + } + + device_config_needed = NOTHING; + for (container = 0; container < dev->maximum_num_containers; + ++container) { + if ((dev->fsa_dev[container].config_waiting_on == 0) + && (dev->fsa_dev[container].config_needed != NOTHING)) { + device_config_needed = + dev->fsa_dev[container].config_needed; + dev->fsa_dev[container].config_needed = NOTHING; + break; + } + } + if (device_config_needed == NOTHING) + return; + + /* + * If we decided that a re-configuration needs to be done, + * schedule it here on the way out the door, please close the door + * behind you. + */ + + busy = 0; + + + /* + * Find the Scsi_Device associated with the SCSI address, + * and mark it as changed, invalidating the cache. This deals + * with changes to existing device IDs. + */ + + if (!dev || !dev->scsi_host_ptr) + return; + /* + * force reload of disk info via probe_container + */ + if ((device_config_needed == CHANGE) + && (dev->fsa_dev[container].valid == 1)) + dev->fsa_dev[container].valid = 2; + if ((device_config_needed == CHANGE) || + (device_config_needed == ADD)) + probe_container(dev, container); + device = scsi_device_lookup(dev->scsi_host_ptr, + CONTAINER_TO_CHANNEL(container), + CONTAINER_TO_ID(container), + CONTAINER_TO_LUN(container)); + if (device) { + switch (device_config_needed) { + case DELETE: + scsi_remove_device(device); + break; + case CHANGE: + if (!dev->fsa_dev[container].valid) { + scsi_remove_device(device); + break; + } + scsi_rescan_device(&device->sdev_gendev); + + default: + break; + } + scsi_device_put(device); + } + if (device_config_needed == ADD) { + scsi_add_device(dev->scsi_host_ptr, + CONTAINER_TO_CHANNEL(container), + CONTAINER_TO_ID(container), + CONTAINER_TO_LUN(container)); + } + +} + /** * aac_command_thread - command processing thread * @dev: Adapter to monitor @@ -860,6 +1123,7 @@ int aac_command_thread(struct aac_dev * dev) aifcmd = (struct aac_aifcmd *) hw_fib->data; if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { /* Handle Driver Notify Events */ + aac_handle_aif(dev, fib); *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, (u16)sizeof(u32)); } else { @@ -872,7 +1136,15 @@ int aac_command_thread(struct aac_dev * dev) unsigned num; struct hw_fib ** hw_fib_pool, ** hw_fib_p; struct fib ** fib_pool, ** fib_p; - + + /* Sniff events */ + if ((aifcmd->command == + cpu_to_le32(AifCmdEventNotify)) || + (aifcmd->command == + cpu_to_le32(AifCmdJobProgress))) { + aac_handle_aif(dev, fib); + } + time_now = jiffies/HZ; /* -- cgit v0.10.2 From 08efb7b6116927c8b6e0af5064448e3aa13300e6 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 20 Sep 2005 12:56:36 -0700 Subject: [SCSI] aacraid: error return checking This patch adds some additional error return checking and error return value propagation during initialization. Also, the deprecation of pci_module_init with pci_register_driver along with the change in return values. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 31d96b9..de8490a 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -748,7 +748,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, unique_id++; } - if (pci_enable_device(pdev)) + error = pci_enable_device(pdev); + if (error) goto out; if (pci_set_dma_mask(pdev, 0xFFFFFFFFULL) || @@ -800,7 +801,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, goto out_free_fibs; aac->maximum_num_channels = aac_drivers[index].channels; - aac_get_adapter_info(aac); + error = aac_get_adapter_info(aac); + if (error < 0) + goto out_deinit; /* * Lets override negotiations and drop the maximum SG limit to 34 @@ -928,8 +931,8 @@ static int __init aac_init(void) printk(KERN_INFO "Adaptec %s driver (%s)\n", AAC_DRIVERNAME, aac_driver_version); - error = pci_module_init(&aac_pci_driver); - if (error) + error = pci_register_driver(&aac_pci_driver); + if (error < 0) return error; aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops); -- cgit v0.10.2 From 9203344cb8ecc554a1d36eae6661235ed422cf59 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 20 Sep 2005 12:56:50 -0700 Subject: [SCSI] aacraid: initialization timeout Received from Mark Salyzyn from Adaptec. In the rare instances where the adapter, or the motherboard, is misbehaving; driver initialization or shutdown becomes problematic. By introducing a 3 minute timeout on the first interrupt driven command during initialization, or the issuance of the adapter shutdown command during driver unload, we can resolve the lockup problems induced by common (but rare) hardware misbehaviors. The timeout during initialization, should it occur, is accompanied by a message presented to the console and the logs indicating that the user should inspect and resolve problems with interrupt routing. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 85d133c..a0735a2 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -692,7 +692,7 @@ int aac_get_adapter_info(struct aac_dev* dev) fibptr, sizeof(*info), FsaNormal, - 1, 1, + -1, 1, /* First `interrupt' command uses special wait */ NULL, NULL); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 7f11c85..9e054a5 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -195,7 +195,7 @@ int aac_send_shutdown(struct aac_dev * dev) fibctx, sizeof(struct aac_close), FsaNormal, - 1, 1, + -2 /* Timeout silently */, 1, NULL, NULL); if (status == 0) diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 69985b08..3b983f3 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "aacraid.h" @@ -541,7 +542,34 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority if (wait) { spin_unlock_irqrestore(&fibptr->event_lock, flags); - down(&fibptr->event_wait); + /* Only set for first known interruptable command */ + if (wait < 0) { + /* + * *VERY* Dangerous to time out a command, the + * assumption is made that we have no hope of + * functioning because an interrupt routing or other + * hardware failure has occurred. + */ + unsigned long count = 36000000L; /* 3 minutes */ + unsigned long qflags; + while (down_trylock(&fibptr->event_wait)) { + if (--count == 0) { + spin_lock_irqsave(q->lock, qflags); + q->numpending--; + list_del(&fibptr->queue); + spin_unlock_irqrestore(q->lock, qflags); + if (wait == -1) { + printk(KERN_ERR "aacraid: fib_send: first asynchronous command timed out.\n" + "Usually a result of a PCI interrupt routing problem;\n" + "update mother board BIOS or consider utilizing one of\n" + "the SAFE mode kernel options (acpi, apic etc)\n"); + } + return -ETIMEDOUT; + } + udelay(5); + } + } else + down(&fibptr->event_wait); if(fibptr->done == 0) BUG(); -- cgit v0.10.2 From 63a70eeaafe0e17e7f45cba495cb457d06070419 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 20 Sep 2005 12:57:04 -0700 Subject: [SCSI] aacraid: fib size math fix Received from Mark Salyzyn from Adaptec. The size of the command packet's scatter gather list maximum size was miscalculated in the low range leading to the driver initialization limiting the maximum i/o size that could go to the Adapter. There were no negative operational side effects resulting from this bad math, only a subtle limit in performance of the Adapter at the top end of the range. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index a0735a2..93416f7 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -843,8 +843,8 @@ int aac_get_adapter_info(struct aac_dev* dev) if (!(dev->raw_io_interface)) { dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write) + sizeof(struct sgmap)) / - sizeof(struct sgmap); + sizeof(struct aac_write) + sizeof(struct sgentry)) / + sizeof(struct sgentry); if (dev->dac_support) { /* * 38 scatter gather elements @@ -853,8 +853,8 @@ int aac_get_adapter_info(struct aac_dev* dev) (dev->max_fib_size - sizeof(struct aac_fibhdr) - sizeof(struct aac_write64) + - sizeof(struct sgmap64)) / - sizeof(struct sgmap64); + sizeof(struct sgentry64)) / + sizeof(struct sgentry64); } dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 9e054a5..59a341b 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -313,8 +313,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) dev->max_fib_size = sizeof(struct hw_fib); dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write) + sizeof(struct sgmap)) - / sizeof(struct sgmap); + - sizeof(struct aac_write) + sizeof(struct sgentry)) + / sizeof(struct sgentry); dev->raw_io_64 = 0; if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && @@ -349,8 +349,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) dev->max_fib_size = 512; dev->sg_tablesize = host->sg_tablesize = (512 - sizeof(struct aac_fibhdr) - - sizeof(struct aac_write) + sizeof(struct sgmap)) - / sizeof(struct sgmap); + - sizeof(struct aac_write) + sizeof(struct sgentry)) + / sizeof(struct sgentry); host->can_queue = AAC_NUM_IO_FIB; } else if (acbsize == 2048) { host->max_sectors = 512; -- cgit v0.10.2 From 1640a2c385a860ef25be4a8d18a528c4b6f02bd6 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Tue, 20 Sep 2005 12:57:11 -0700 Subject: [SCSI] aacraid: remove aac_insert_entry Received from Mark Salyzyn from Adaptec. High Priority Queues have *never* been used in the entire history of the aac based adapters. Associated with this, aac_insert_entry can be removed, SavedIrql can be removed & padding variable can be removed. With the movement of SavedIrql out & replaced with an automatic variable qflags, the locking can be refined somewhat. The sparse warnings did not catch the need for byte swapping in the 'dprintk' debugging print macros, so fixed this up when this code was moved outside of the now refined locking. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 0880f48..4a99d2f 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -306,7 +306,6 @@ enum aac_queue_types { */ #define FsaNormal 1 -#define FsaHigh 2 /* * Define the FIB. The FIB is the where all the requested data and @@ -550,8 +549,6 @@ struct aac_queue { /* This is only valid for adapter to host command queues. */ spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */ spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ - unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ - u32 padding; /* Padding - FIXME - can remove I believe */ struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 3b983f3..e4d543a 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -271,40 +271,22 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr /* Interrupt Moderation, only interrupt for first two entries */ if (idx != le32_to_cpu(*(q->headers.consumer))) { if (--idx == 0) { - if (qid == AdapHighCmdQueue) - idx = ADAP_HIGH_CMD_ENTRIES; - else if (qid == AdapNormCmdQueue) + if (qid == AdapNormCmdQueue) idx = ADAP_NORM_CMD_ENTRIES; - else if (qid == AdapHighRespQueue) - idx = ADAP_HIGH_RESP_ENTRIES; - else if (qid == AdapNormRespQueue) + else idx = ADAP_NORM_RESP_ENTRIES; } if (idx != le32_to_cpu(*(q->headers.consumer))) *nonotify = 1; } - if (qid == AdapHighCmdQueue) { - if (*index >= ADAP_HIGH_CMD_ENTRIES) - *index = 0; - } else if (qid == AdapNormCmdQueue) { + if (qid == AdapNormCmdQueue) { if (*index >= ADAP_NORM_CMD_ENTRIES) *index = 0; /* Wrap to front of the Producer Queue. */ - } - else if (qid == AdapHighRespQueue) - { - if (*index >= ADAP_HIGH_RESP_ENTRIES) - *index = 0; - } - else if (qid == AdapNormRespQueue) - { + } else { if (*index >= ADAP_NORM_RESP_ENTRIES) *index = 0; /* Wrap to front of the Producer Queue. */ } - else { - printk("aacraid: invalid qid\n"); - BUG(); - } if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ printk(KERN_WARNING "Queue %d full, %u outstanding.\n", @@ -336,12 +318,8 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f { struct aac_entry * entry = NULL; int map = 0; - struct aac_queue * q = &dev->queues->queue[qid]; - - spin_lock_irqsave(q->lock, q->SavedIrql); - if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue) - { + if (qid == AdapNormCmdQueue) { /* if no entries wait for some if caller wants to */ while (!aac_get_entry(dev, qid, &entry, index, nonotify)) { @@ -352,9 +330,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f */ entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); map = 1; - } - else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) - { + } else { while(!aac_get_entry(dev, qid, &entry, index, nonotify)) { /* if no entries wait for some if caller wants to */ @@ -377,42 +353,6 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f return 0; } - -/** - * aac_insert_entry - insert a queue entry - * @dev: Adapter - * @index: Index of entry to insert - * @qid: Queue number - * @nonotify: Suppress adapter notification - * - * Gets the next free QE off the requested priorty adapter command - * queue and associates the Fib with the QE. The QE represented by - * index is ready to insert on the queue when this routine returns - * success. - */ - -static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify) -{ - struct aac_queue * q = &dev->queues->queue[qid]; - - if(q == NULL) - BUG(); - *(q->headers.producer) = cpu_to_le32(index + 1); - spin_unlock_irqrestore(q->lock, q->SavedIrql); - - if (qid == AdapHighCmdQueue || - qid == AdapNormCmdQueue || - qid == AdapHighRespQueue || - qid == AdapNormRespQueue) - { - if (!nonotify) - aac_adapter_notify(dev, qid); - } - else - printk("Suprise insert!\n"); - return 0; -} - /* * Define the highest level of host to adapter communication routines. * These routines will support host to adapter FS commuication. These @@ -441,12 +381,13 @@ static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned l int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data) { u32 index; - u32 qid; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_queue * q; unsigned long flags = 0; + unsigned long qflags; + if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) return -EBUSY; /* @@ -499,26 +440,8 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority * Get a queue entry connect the FIB to it and send an notify * the adapter a command is ready. */ - if (priority == FsaHigh) { - hw_fib->header.XferState |= cpu_to_le32(HighPriority); - qid = AdapHighCmdQueue; - } else { - hw_fib->header.XferState |= cpu_to_le32(NormalPriority); - qid = AdapNormCmdQueue; - } - q = &dev->queues->queue[qid]; + hw_fib->header.XferState |= cpu_to_le32(NormalPriority); - if(wait) - spin_lock_irqsave(&fibptr->event_lock, flags); - if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0) - return -EWOULDBLOCK; - dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); - dprintk((KERN_DEBUG "Fib contents:.\n")); - dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); - dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); - dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); - dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); - dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * Fill in the Callback and CallbackContext if we are not * going to wait. @@ -527,15 +450,33 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority fibptr->callback = callback; fibptr->callback_data = callback_data; } - FIB_COUNTER_INCREMENT(aac_config.FibsSent); - list_add_tail(&fibptr->queue, &q->pendingq); - q->numpending++; fibptr->done = 0; fibptr->flags = 0; - if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0) - return -EWOULDBLOCK; + FIB_COUNTER_INCREMENT(aac_config.FibsSent); + + dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); + dprintk((KERN_DEBUG "Fib contents:.\n")); + dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); + dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); + dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); + + q = &dev->queues->queue[AdapNormCmdQueue]; + + if(wait) + spin_lock_irqsave(&fibptr->event_lock, flags); + spin_lock_irqsave(q->lock, qflags); + aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr); + + list_add_tail(&fibptr->queue, &q->pendingq); + q->numpending++; + *(q->headers.producer) = cpu_to_le32(index + 1); + spin_unlock_irqrestore(q->lock, qflags); + if (!(nointr & aac_config.irq_mod)) + aac_adapter_notify(dev, AdapNormCmdQueue); /* * If the caller wanted us to wait for response wait now. */ @@ -651,15 +592,9 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid) case HostNormCmdQueue: notify = HostNormCmdNotFull; break; - case HostHighCmdQueue: - notify = HostHighCmdNotFull; - break; case HostNormRespQueue: notify = HostNormRespNotFull; break; - case HostHighRespQueue: - notify = HostHighRespNotFull; - break; default: BUG(); return; @@ -681,9 +616,13 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) { struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_dev * dev = fibptr->dev; + struct aac_queue * q; unsigned long nointr = 0; - if (hw_fib->header.XferState == 0) + unsigned long qflags; + + if (hw_fib->header.XferState == 0) { return 0; + } /* * If we plan to do anything check the structure type first. */ @@ -698,37 +637,21 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) * send the completed cdb to the adapter. */ if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { + u32 index; hw_fib->header.XferState |= cpu_to_le32(HostProcessed); - if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { - u32 index; - if (size) - { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(hw_fib->header.SenderSize)) - return -EMSGSIZE; - hw_fib->header.Size = cpu_to_le16(size); - } - if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { - return -EWOULDBLOCK; - } - if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { - } - } else if (hw_fib->header.XferState & - cpu_to_le32(NormalPriority)) { - u32 index; - - if (size) { - size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(hw_fib->header.SenderSize)) - return -EMSGSIZE; - hw_fib->header.Size = cpu_to_le16(size); - } - if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0) - return -EWOULDBLOCK; - if (aac_insert_entry(dev, index, AdapNormRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) - { - } + if (size) { + size += sizeof(struct aac_fibhdr); + if (size > le16_to_cpu(hw_fib->header.SenderSize)) + return -EMSGSIZE; + hw_fib->header.Size = cpu_to_le16(size); } + q = &dev->queues->queue[AdapNormRespQueue]; + spin_lock_irqsave(q->lock, qflags); + aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr); + *(q->headers.producer) = cpu_to_le32(index + 1); + spin_unlock_irqrestore(q->lock, qflags); + if (!(nointr & (int)aac_config.irq_mod)) + aac_adapter_notify(dev, AdapNormRespQueue); } else { -- cgit v0.10.2 From c5bd50a9533533d7b9ac3469fa679b2368e7e26c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 26 Sep 2005 16:06:03 -0700 Subject: [SPARC64]: Simplify Spitfire D-cache page flush. It tries to batch up the tag loads and comparisons, and then the stores. And this is just complicated instead of efficient. Also, make the symbol of the Cheetah version more grepable. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index b2ee9b5..5ff5e42 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S @@ -144,42 +144,29 @@ __flush_icache_page: /* %o0 = phys_page */ #define DTAG_MASK 0x3 + /* This routine is Spitfire specific so the hardcoded + * D-cache size and line-size are OK. + */ .align 64 .globl __flush_dcache_page __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ sethi %uhi(PAGE_OFFSET), %g1 sllx %g1, 32, %g1 - sub %o0, %g1, %o0 - clr %o4 - srlx %o0, 11, %o0 - sethi %hi(1 << 14), %o2 -1: ldxa [%o4] ASI_DCACHE_TAG, %o3 ! LSU Group - add %o4, (1 << 5), %o4 ! IEU0 - ldxa [%o4] ASI_DCACHE_TAG, %g1 ! LSU Group - add %o4, (1 << 5), %o4 ! IEU0 - ldxa [%o4] ASI_DCACHE_TAG, %g2 ! LSU Group o3 available - add %o4, (1 << 5), %o4 ! IEU0 - andn %o3, DTAG_MASK, %o3 ! IEU1 - ldxa [%o4] ASI_DCACHE_TAG, %g3 ! LSU Group - add %o4, (1 << 5), %o4 ! IEU0 - andn %g1, DTAG_MASK, %g1 ! IEU1 - cmp %o0, %o3 ! IEU1 Group - be,a,pn %xcc, dflush1 ! CTI - sub %o4, (4 << 5), %o4 ! IEU0 (Group) - cmp %o0, %g1 ! IEU1 Group - andn %g2, DTAG_MASK, %g2 ! IEU0 - be,a,pn %xcc, dflush2 ! CTI - sub %o4, (3 << 5), %o4 ! IEU0 (Group) - cmp %o0, %g2 ! IEU1 Group - andn %g3, DTAG_MASK, %g3 ! IEU0 - be,a,pn %xcc, dflush3 ! CTI - sub %o4, (2 << 5), %o4 ! IEU0 (Group) - cmp %o0, %g3 ! IEU1 Group - be,a,pn %xcc, dflush4 ! CTI - sub %o4, (1 << 5), %o4 ! IEU0 -2: cmp %o4, %o2 ! IEU1 Group - bne,pt %xcc, 1b ! CTI - nop ! IEU0 + sub %o0, %g1, %o0 ! physical address + srlx %o0, 11, %o0 ! make D-cache TAG + sethi %hi(1 << 14), %o2 ! D-cache size + sub %o2, (1 << 5), %o2 ! D-cache line size +1: ldxa [%o2] ASI_DCACHE_TAG, %o3 ! load D-cache TAG + andcc %o3, DTAG_MASK, %g0 ! Valid? + be,pn %xcc, 2f ! Nope, branch + andn %o3, DTAG_MASK, %o3 ! Clear valid bits + cmp %o3, %o0 ! TAG match? + bne,pt %xcc, 2f ! Nope, branch + nop + stxa %g0, [%o2] ASI_DCACHE_TAG ! Invalidate TAG + membar #Sync +2: brnz,pt %o2, 1b + sub %o2, (1 << 5), %o2 ! D-cache line size /* The I-cache does not snoop local stores so we * better flush that too when necessary. @@ -189,20 +176,10 @@ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ retl nop -dflush1:stxa %g0, [%o4] ASI_DCACHE_TAG - add %o4, (1 << 5), %o4 -dflush2:stxa %g0, [%o4] ASI_DCACHE_TAG - add %o4, (1 << 5), %o4 -dflush3:stxa %g0, [%o4] ASI_DCACHE_TAG - add %o4, (1 << 5), %o4 -dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG - add %o4, (1 << 5), %o4 - membar #Sync - ba,pt %xcc, 2b - nop #endif /* DCACHE_ALIASING_POSSIBLE */ - .previous .text + .previous + .align 32 __prefill_dtlb: rdpr %pstate, %g7 @@ -283,7 +260,7 @@ __cheetah_flush_tlb_pending: /* 26 insns */ wrpr %g7, 0x0, %pstate #ifdef DCACHE_ALIASING_POSSIBLE -flush_dcpage_cheetah: /* 11 insns */ +__cheetah_flush_dcache_page: /* 11 insns */ sethi %uhi(PAGE_OFFSET), %g1 sllx %g1, 32, %g1 sub %o0, %g1, %o0 @@ -329,8 +306,8 @@ cheetah_patch_cachetlbops: #ifdef DCACHE_ALIASING_POSSIBLE sethi %hi(__flush_dcache_page), %o0 or %o0, %lo(__flush_dcache_page), %o0 - sethi %hi(flush_dcpage_cheetah), %o1 - or %o1, %lo(flush_dcpage_cheetah), %o1 + sethi %hi(__cheetah_flush_dcache_page), %o1 + or %o1, %lo(__cheetah_flush_dcache_page), %o1 call cheetah_patch_one mov 11, %o2 #endif /* DCACHE_ALIASING_POSSIBLE */ -- cgit v0.10.2 From 0dc461069879b45a2d5333bd16990f8080a318fd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 26 Sep 2005 16:12:18 -0700 Subject: [SPARC64]: Do not do TLB pre-filling any more. In order to do it correctly on UltraSPARC-III+ and later we'd need to add some complicated code to set the TAG access extension register before loading the TLB. Since this optimization gives questionable gains, it's best to just remove it for now instead of adding the fix for Ultra-III+ Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 8d72f8a..9f6ca62 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -171,8 +171,6 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c : "g1", "g7"); } -extern void __update_mmu_cache(unsigned long mmu_context_hw, unsigned long address, pte_t pte, int code); - void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { struct page *page; @@ -199,10 +197,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p put_cpu(); } - - if (get_thread_fault_code()) - __update_mmu_cache(CTX_NRBITS(vma->vm_mm->context), - address, pte, get_thread_fault_code()); } void flush_dcache_page(struct page *page) diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 5ff5e42..058b812 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S @@ -180,35 +180,6 @@ __flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ .previous - .align 32 -__prefill_dtlb: - rdpr %pstate, %g7 - wrpr %g7, PSTATE_IE, %pstate - mov TLB_TAG_ACCESS, %g1 - stxa %o5, [%g1] ASI_DMMU - stxa %o2, [%g0] ASI_DTLB_DATA_IN - flush %g6 - retl - wrpr %g7, %pstate -__prefill_itlb: - rdpr %pstate, %g7 - wrpr %g7, PSTATE_IE, %pstate - mov TLB_TAG_ACCESS, %g1 - stxa %o5, [%g1] ASI_IMMU - stxa %o2, [%g0] ASI_ITLB_DATA_IN - flush %g6 - retl - wrpr %g7, %pstate - - .globl __update_mmu_cache -__update_mmu_cache: /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */ - srlx %o1, PAGE_SHIFT, %o1 - andcc %o3, FAULT_CODE_DTLB, %g0 - sllx %o1, PAGE_SHIFT, %o5 - bne,pt %xcc, __prefill_dtlb - or %o5, %o0, %o5 - ba,a,pt %xcc, __prefill_itlb - /* Cheetah specific versions, patched at boot time. */ __cheetah_flush_tlb_mm: /* 18 insns */ rdpr %pstate, %g7 -- cgit v0.10.2 From 7625d483a454cbc8090c5d304eea0847210d6b99 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 05:25:59 +0100 Subject: [PATCH] missing asm/irq.h (cs89x0) Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index cdc07cc..a6078ad 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -140,6 +140,7 @@ #include #include +#include #if ALLOW_DMA #include #endif -- cgit v0.10.2 From ce3a161e693388aaa66d43d26156053311a39b7d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 05:49:44 +0100 Subject: [PATCH] useless includes of linux/irq.h in arch/i386 Most of these guys are simply not needed (pulled by other stuff via asm-i386/hardirq.h). One that is not entirely useless is hilarious - arch/i386/oprofile/nmi_timer_int.c includes linux/irq.h... as a way to get linux/errno.h Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index a63351c..838437b2 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index a22a866..5546dde 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index c4abe76..7c6b9c7 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c index 7864ddf..82dffe0 100644 --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c index 0abccb6..1d1e885 100644 --- a/arch/i386/kernel/cpu/mcheck/p4.c +++ b/arch/i386/kernel/cpu/mcheck/p4.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c index ec0614c..3a2e24b 100644 --- a/arch/i386/kernel/cpu/mcheck/p5.c +++ b/arch/i386/kernel/cpu/mcheck/p5.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c index f01b73f..3c035b8 100644 --- a/arch/i386/kernel/cpu/mcheck/p6.c +++ b/arch/i386/kernel/cpu/mcheck/p6.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c index 7bae68f..5b9d2dd 100644 --- a/arch/i386/kernel/cpu/mcheck/winchip.c +++ b/arch/i386/kernel/cpu/mcheck/winchip.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 913be77..0248e08 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -11,10 +11,8 @@ #include #include #include -#include #include #include -#include #include #include #include diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 178f4e9..323ef8a 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -25,8 +24,6 @@ #include #include -#include - #include /* diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 378313b..fb3991e 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 15949fd..27aabfc 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 0178457..72515b8 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -15,7 +15,6 @@ #include #include -#include #include #include #include diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index b45cbf9..7a14fdf 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -47,13 +47,11 @@ #include #include #include -#include #include #ifdef CONFIG_MATH_EMULATION #include #endif -#include #include #include diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 48b55db..218d725 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 5f0a95d..1fb26d0 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c index eddb640..e42e46d3 100644 --- a/arch/i386/kernel/timers/timer_pit.c +++ b/arch/i386/kernel/timers/timer_pit.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 431a551..19e90bd 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -52,7 +52,6 @@ #include #include -#include #include #include "mach_traps.h" diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c index e5a1a83..b4a7455 100644 --- a/arch/i386/mach-default/setup.c +++ b/arch/i386/mach-default/setup.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c index 26ada6f..07fac7e 100644 --- a/arch/i386/mach-visws/setup.c +++ b/arch/i386/mach-visws/setup.c @@ -5,7 +5,6 @@ #include #include -#include #include #include diff --git a/arch/i386/mach-visws/visws_apic.c b/arch/i386/mach-visws/visws_apic.c index 04e6585..3e64fb7 100644 --- a/arch/i386/mach-visws/visws_apic.c +++ b/arch/i386/mach-visws/visws_apic.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c index df123fc..7d8a3ac 100644 --- a/arch/i386/mach-voyager/setup.c +++ b/arch/i386/mach-voyager/setup.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c index cc69875..aa49a33 100644 --- a/arch/i386/mach-voyager/voyager_basic.c +++ b/arch/i386/mach-voyager/voyager_basic.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 46b0cf4..72a1b9c 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c @@ -30,8 +30,6 @@ #include #include -#include - /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c index a9341b0..2b03884 100644 --- a/arch/i386/mach-voyager/voyager_thread.c +++ b/arch/i386/mach-voyager/voyager_thread.c @@ -31,8 +31,6 @@ #include #include -#include - #define THREAD_NAME "kvoyagerd" /* external variables */ diff --git a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c index ad93cdd..930a112 100644 --- a/arch/i386/oprofile/nmi_timer_int.c +++ b/arch/i386/oprofile/nmi_timer_int.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index 2941674..7e7a202 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include "pci.h" diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 326a2ed..281ed8a 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 7b0b9ad..b27c5ac 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -8,25 +8,8 @@ */ #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include - -#include -#include -#include -#include static struct saved_context saved_context; -- cgit v0.10.2 From 24558a0f7a00fccd19a6e6502956463f056ce90e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 06:19:28 +0100 Subject: [PATCH] m32r: missing __iomem in ioremap() declaration Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-m32r/io.h b/include/asm-m32r/io.h index 8e9e481..70ad1c9 100644 --- a/include/asm-m32r/io.h +++ b/include/asm-m32r/io.h @@ -60,7 +60,7 @@ __ioremap(unsigned long offset, unsigned long size, unsigned long flags); * address. */ -static inline void * ioremap(unsigned long offset, unsigned long size) +static inline void __iomem *ioremap(unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } -- cgit v0.10.2 From c74dbac71419cdeaca8cd637ee666d6947961695 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 06:19:28 +0100 Subject: [PATCH] m32r: set CHECKFLAGS properly We do _not_ need "sparse" in sparse arguments ;-) What we do need is __BIG_ENDIAN__; right now unconditional, when m32r starts using CPU_LITTLE_ENDIAN, we'll need to adjust. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/m32r/Makefile b/arch/m32r/Makefile index dd4418d..983d438 100644 --- a/arch/m32r/Makefile +++ b/arch/m32r/Makefile @@ -24,7 +24,7 @@ aflags-$(CONFIG_ISA_M32R) += -DNO_FPU -Wa,-no-bitinst CFLAGS += $(cflags-y) AFLAGS += $(aflags-y) -CHECKFLAGS := $(CHECK) -D__m32r__ +CHECKFLAGS += -D__m32r__ -D__BIG_ENDIAN__=1 head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o -- cgit v0.10.2 From a880948b2b88c05af9a471ca5c52883e64d3f7b8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 06:19:28 +0100 Subject: [PATCH] m32r: more basic __user annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c index 6c6855f..ce16bbe 100644 --- a/arch/m32r/lib/usercopy.c +++ b/arch/m32r/lib/usercopy.c @@ -13,7 +13,7 @@ #include unsigned long -__generic_copy_to_user(void *to, const void *from, unsigned long n) +__generic_copy_to_user(void __user *to, const void *from, unsigned long n) { prefetch(from); if (access_ok(VERIFY_WRITE, to, n)) @@ -22,7 +22,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) } unsigned long -__generic_copy_from_user(void *to, const void *from, unsigned long n) +__generic_copy_from_user(void *to, const void __user *from, unsigned long n) { prefetchw(to); if (access_ok(VERIFY_READ, from, n)) @@ -111,7 +111,7 @@ do { \ #endif /* CONFIG_ISA_DUAL_ISSUE */ long -__strncpy_from_user(char *dst, const char *src, long count) +__strncpy_from_user(char *dst, const char __user *src, long count) { long res; __do_strncpy_from_user(dst, src, count, res); @@ -119,7 +119,7 @@ __strncpy_from_user(char *dst, const char *src, long count) } long -strncpy_from_user(char *dst, const char *src, long count) +strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) @@ -222,7 +222,7 @@ do { \ #endif /* not CONFIG_ISA_DUAL_ISSUE */ unsigned long -clear_user(void *to, unsigned long n) +clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) __do_clear_user(to, n); @@ -230,7 +230,7 @@ clear_user(void *to, unsigned long n) } unsigned long -__clear_user(void *to, unsigned long n) +__clear_user(void __user *to, unsigned long n) { __do_clear_user(to, n); return n; @@ -244,7 +244,7 @@ __clear_user(void *to, unsigned long n) #ifdef CONFIG_ISA_DUAL_ISSUE -long strnlen_user(const char *s, long n) +long strnlen_user(const char __user *s, long n) { unsigned long mask = -__addr_ok(s); unsigned long res; @@ -313,7 +313,7 @@ long strnlen_user(const char *s, long n) #else /* not CONFIG_ISA_DUAL_ISSUE */ -long strnlen_user(const char *s, long n) +long strnlen_user(const char __user *s, long n) { unsigned long mask = -__addr_ok(s); unsigned long res; diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h index 93d863c..0da7c47 100644 --- a/include/asm-m32r/uaccess.h +++ b/include/asm-m32r/uaccess.h @@ -208,7 +208,8 @@ extern void __get_user_4(void); * On error, the variable @x is set to zero. */ #define get_user(x,ptr) \ -({ int __ret_gu,__val_gu; \ +({ int __ret_gu; \ + unsigned long __val_gu; \ __chk_user_ptr(ptr); \ switch(sizeof (*(ptr))) { \ case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \ @@ -403,7 +404,8 @@ struct __large_struct { unsigned long buf[100]; }; #define __get_user_nocheck(x,ptr,size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + unsigned long __gu_val; \ __get_user_size(__gu_val,(ptr),(size),__gu_err); \ (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \ @@ -594,8 +596,8 @@ static inline unsigned long __generic_copy_to_user_nocheck(void __user *to, return n; } -unsigned long __generic_copy_to_user(void *, const void *, unsigned long); -unsigned long __generic_copy_from_user(void *, const void *, unsigned long); +unsigned long __generic_copy_to_user(void __user *, const void *, unsigned long); +unsigned long __generic_copy_from_user(void *, const void __user *, unsigned long); /** * __copy_to_user: - Copy a block of data into user space, with less checking. -- cgit v0.10.2 From 0b1556945475e8529328edf98ff0d201ed133edb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 26 Sep 2005 07:49:27 +0100 Subject: [PATCH] missing dependency on arm O= builds arm maketools needs include/asm-arm in place in the build tree. On normal builds it's always there, of course, but on O= it's created (by generic code) too late - when we get to asm-offset.h. We used to get away with that by accident - creation of include/asm-arm/arch symlink creates include/asm-arm and it happened to go before maketools. However, we did not have such dependency, so that luck didn't last - now maketools is picked first and we are screwed. Both the symlink and maketools are prerequisites of the same target (archprepare). This fix is obvious - make the latter explicitly depend on the former and be done with that. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 130e622..7779f2d 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -175,10 +175,10 @@ else endif @touch $@ -archprepare: maketools include/asm-arm/.arch +archprepare: maketools .PHONY: maketools FORCE -maketools: include/linux/version.h FORCE +maketools: include/linux/version.h include/asm-arm/.arch FORCE $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h # Convert bzImage to zImage -- cgit v0.10.2 From f02b16bea2d8411b21a531fc381e066985895387 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 26 Sep 2005 21:12:26 -0700 Subject: [IB] mthca: Round up number of slots in HCA context memory table When allocating a table for mem-free HCA context, don't assume that obj_size * nobj is an even multiple of MTHCA_TABLE_CHUNK_SIZE. In particular, make sure we allocate at least one slot even if the table is smaller than MTHCA_TABLE_CHUNK_SIZE. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index d0c41fe..7bd7a4b 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, int i; u8 status; - num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE; + num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE; table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL); if (!table) -- cgit v0.10.2 From 667347f1ca7e099f6833551f194cf2bcc778871b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 12:07:44 -0700 Subject: [NEIGH]: Add debugging check when adding timers. If we double-add a neighbour entry timer, which should be impossible but has been reported, dump the current state of the entry so that we can debug this. Signed-off-by: David S. Miller diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 5f16008..4128fc7 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -727,6 +727,13 @@ static __inline__ int neigh_max_probes(struct neighbour *n) p->ucast_probes + p->app_probes + p->mcast_probes); } +static inline void neigh_add_timer(struct neighbour *n, unsigned long when) +{ + if (unlikely(mod_timer(&n->timer, when))) { + printk("NEIGH: BUG, double timer add, state is %x\n", + n->nud_state); + } +} /* Called when a timer expires for a neighbour entry. */ @@ -811,8 +818,7 @@ static void neigh_timer_handler(unsigned long arg) neigh_hold(neigh); if (time_before(next, jiffies + HZ/2)) next = jiffies + HZ/2; - neigh->timer.expires = next; - add_timer(&neigh->timer); + neigh_add_timer(neigh, next); } if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) { struct sk_buff *skb = skb_peek(&neigh->arp_queue); @@ -854,8 +860,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) atomic_set(&neigh->probes, neigh->parms->ucast_probes); neigh->nud_state = NUD_INCOMPLETE; neigh_hold(neigh); - neigh->timer.expires = now + 1; - add_timer(&neigh->timer); + neigh_add_timer(neigh, now + 1); } else { neigh->nud_state = NUD_FAILED; write_unlock_bh(&neigh->lock); @@ -868,8 +873,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) NEIGH_PRINTK2("neigh %p is delayed.\n", neigh); neigh_hold(neigh); neigh->nud_state = NUD_DELAY; - neigh->timer.expires = jiffies + neigh->parms->delay_probe_time; - add_timer(&neigh->timer); + neigh_add_timer(neigh, + jiffies + neigh->parms->delay_probe_time); } if (neigh->nud_state == NUD_INCOMPLETE) { @@ -1015,10 +1020,10 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, neigh_del_timer(neigh); if (new & NUD_IN_TIMER) { neigh_hold(neigh); - neigh->timer.expires = jiffies + + neigh_add_timer(neigh, (jiffies + ((new & NUD_REACHABLE) ? - neigh->parms->reachable_time : 0); - add_timer(&neigh->timer); + neigh->parms->reachable_time : + 0))); } neigh->nud_state = new; } -- cgit v0.10.2 From c94e39418ab6eccf863581f4e0d847da0080b2d3 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 27 Sep 2005 12:12:42 -0700 Subject: [TG3]: 5780 PHY fixes Fix 5780 PHY related problems: 1. MAC_RX_MODE reset must be done before setting up the MAC_MODE register on 5705_PLUS chips or the chip will stop receiving after a while. The MAC_RX_MODE reset is needed to prevent intermittently losing the first receive packet on serdes chips. 2. Skip MAC loopback test on 5780 because of hardware errata. Normal traffic including PHY loopback is not affected by the errata. 3. PHY loopback fails intermittently on 5708S and this is fixed by putting the PHY in loopback mode first before programming the MAC mode register. A MAC_RX_MODE reset is also added. 4. Return -EINVAL in tg3_nway_reset() if device is in TBI mode. Allow nway_reset if 5780S is in parallel detect mode. 5. Add missing PHY IDs in KNOWN_PHY_ID() macro. Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 81f4aed..ef2f1fd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5806,6 +5806,13 @@ static int tg3_reset_hw(struct tg3 *tp) } memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + /* reset to prevent losing 1st rx packet intermittently */ + tw32_f(MAC_RX_MODE, RX_MODE_RESET); + udelay(10); + } + tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); @@ -5937,7 +5944,7 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } @@ -7360,12 +7367,17 @@ static int tg3_nway_reset(struct net_device *dev) if (!netif_running(dev)) return -EAGAIN; + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + return -EINVAL; + spin_lock_bh(&tp->lock); r = -EINVAL; tg3_readphy(tp, MII_BMCR, &bmcr); if (!tg3_readphy(tp, MII_BMCR, &bmcr) && - (bmcr & BMCR_ANENABLE)) { - tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); + ((bmcr & BMCR_ANENABLE) || + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART | + BMCR_ANENABLE); r = 0; } spin_unlock_bh(&tp->lock); @@ -7927,19 +7939,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) struct tg3_rx_buffer_desc *desc; if (loopback_mode == TG3_MAC_LOOPBACK) { + /* HW errata - mac loopback fails in some cases on 5780. + * Normal traffic and PHY loopback are not affected by + * errata. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + return 0; + mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; tw32(MAC_MODE, mac_mode); } else if (loopback_mode == TG3_PHY_LOOPBACK) { + tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | + BMCR_SPEED1000); + udelay(40); + /* reset to prevent losing 1st rx packet intermittently */ + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + tw32_f(MAC_RX_MODE, RX_MODE_RESET); + udelay(10); + tw32_f(MAC_RX_MODE, tp->rx_mode); + } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) mac_mode &= ~MAC_MODE_LINK_POLARITY; tw32(MAC_MODE, mac_mode); - - tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | - BMCR_SPEED1000); } else return -EINVAL; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c184b77..2e733c6 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2246,6 +2246,7 @@ struct tg3 { (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ + (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \ (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; -- cgit v0.10.2 From f9804ddbeec2ea709255830a8822bfb4e7584f6a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 27 Sep 2005 12:13:10 -0700 Subject: [TG3]: misc. fixes Fix interrupt test handler by adding check for IRQ assertion in PCI_STATE register in addition to the status block updated bit. Add test for valid ethernet address in tg3_set_mac_addr(). Add tg3_bus_string() to setup the PCI bus speed/width string for all PCI/PCIX/PCI Express devices. This is used to print the bus type during init_one(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ef2f1fd..0ac8db2 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; - if (sblk->status & SD_STATUS_UPDATED) { + if ((sblk->status & SD_STATUS_UPDATED) || + !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); return IRQ_RETVAL(1); @@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); spin_lock_bh(&tp->lock); @@ -10349,6 +10353,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) }; } +static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) +{ + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + strcpy(str, "PCI Express"); + return str; + } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f; + + strcpy(str, "PCIX:"); + + if ((clock_ctrl == 7) || + ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) == + GRC_MISC_CFG_BOARD_ID_5704CIOBE)) + strcat(str, "133MHz"); + else if (clock_ctrl == 0) + strcat(str, "33MHz"); + else if (clock_ctrl == 2) + strcat(str, "50MHz"); + else if (clock_ctrl == 4) + strcat(str, "66MHz"); + else if (clock_ctrl == 6) + strcat(str, "100MHz"); + else if (clock_ctrl == 7) + strcat(str, "133MHz"); + } else { + strcpy(str, "PCI:"); + if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) + strcat(str, "66MHz"); + else + strcat(str, "33MHz"); + } + if (tp->tg3_flags & TG3_FLAG_PCI_32BIT) + strcat(str, ":32-bit"); + else + strcat(str, ":64-bit"); + return str; +} + static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) { struct pci_dev *peer; @@ -10411,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, struct net_device *dev; struct tg3 *tp; int i, err, pci_using_dac, pm_cap; + char str[40]; if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -10656,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ", dev->name, tp->board_part_number, tp->pci_chip_rev_id, tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""), - ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ? - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") : - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")), - ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"), + tg3_bus_string(tp, str), (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); for (i = 0; i < 6; i++) -- cgit v0.10.2 From c8a6c2963982c68475f409aeee21aa80b923cb9c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 12:13:38 -0700 Subject: [TG3]: Update driver version and release date. Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0ac8db2..25f85fb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.40" -#define DRV_MODULE_RELDATE "September 15, 2005" +#define DRV_MODULE_VERSION "3.41" +#define DRV_MODULE_RELDATE "September 27, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v0.10.2 From 59175839783287d3b03f18460bb3539c69300837 Mon Sep 17 00:00:00 2001 From: Krzysztof Benedyczak Date: Tue, 27 Sep 2005 22:21:36 +0200 Subject: [PATCH] Make POSIX message queue sys_mq_open() honor umask We ignored umask when creating new queues via mq_open (when creating with open() on mqueue fs it is ok of course). According to the specification this a bug. This trivial patch fixes this. Signed-off-by: Krzysztof Benedyczak Signed-off-by: Linus Torvalds diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 3a92601..a0f18c9 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -611,6 +611,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, dentry->d_fsdata = &attr; } + mode &= ~current->fs->umask; ret = vfs_create(dir->d_inode, dentry, mode, NULL); dentry->d_fsdata = NULL; if (ret) -- cgit v0.10.2 From a1c337afaf4ec4d4eabc75a5e1170d03161de4e1 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 27 Sep 2005 13:54:44 -0700 Subject: [IB] mthca: fix hw_ver value returned from mthca_query_device The IB spec defines the field to be 32 bits, not 16 bits. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 1c1c2e2..3f5319a 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -84,7 +84,7 @@ static int mthca_query_device(struct ib_device *ibdev, props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 0xffffff; props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); - props->hw_ver = be16_to_cpup((__be16 *) (out_mad->data + 32)); + props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); memcpy(&props->sys_image_guid, out_mad->data + 4, 8); memcpy(&props->node_guid, out_mad->data + 12, 8); -- cgit v0.10.2 From bc8dfcb93970ad7139c976356bfc99d7e251deaf Mon Sep 17 00:00:00 2001 From: Daniel Phillips Date: Tue, 27 Sep 2005 15:22:35 -0700 Subject: [NET]: Use non-recursive algorithm in skb_copy_datagram_iovec() Use iteration instead of recursion. Fraglists within fraglists should never occur, so we BUG check this. Signed-off-by: Daniel Phillips Signed-off-by: David S. Miller diff --git a/net/core/datagram.c b/net/core/datagram.c index da9bf71..81987df 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -211,74 +211,45 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, struct iovec *to, int len) { - int start = skb_headlen(skb); - int i, copy = start - offset; - - /* Copy header. */ - if (copy > 0) { - if (copy > len) - copy = len; - if (memcpy_toiovec(to, skb->data + offset, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } + int i, err, fraglen, end = 0; + struct sk_buff *next = skb_shinfo(skb)->frag_list; +next_skb: + fraglen = skb_headlen(skb); + i = -1; - /* Copy paged appendix. Hmm... why does this look so complicated? */ - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); + while (1) { + int start = end; - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - int err; - u8 *vaddr; - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - struct page *page = frag->page; + if ((end += fraglen) > offset) { + int copy = end - offset, o = offset - start; if (copy > len) copy = len; - vaddr = kmap(page); - err = memcpy_toiovec(to, vaddr + frag->page_offset + - offset - start, copy); - kunmap(page); + if (i == -1) + err = memcpy_toiovec(to, skb->data + o, copy); + else { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + void *p = kmap(page) + frag->page_offset + o; + err = memcpy_toiovec(to, p, copy); + kunmap(page); + } if (err) goto fault; if (!(len -= copy)) return 0; offset += copy; } - start = end; + if (++i >= skb_shinfo(skb)->nr_frags) + break; + fraglen = skb_shinfo(skb)->frags[i].size; } - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - if (skb_copy_datagram_iovec(list, - offset - start, - to, copy)) - goto fault; - if ((len -= copy) == 0) - return 0; - offset += copy; - } - start = end; - } + if (next) { + skb = next; + BUG_ON(skb_shinfo(skb)->frag_list); + next = skb->next; + goto next_skb; } - if (!len) - return 0; - fault: return -EFAULT; } -- cgit v0.10.2 From 2d7ceece08ad940d0ceac98ab1b5a3b82dfc2a0a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Sep 2005 15:22:58 -0700 Subject: [NET]: Prefetch dev->qdisc_lock in dev_queue_xmit() We know the lock is going to be taken. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index 37c8810..9066c87 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1259,6 +1259,8 @@ int dev_queue_xmit(struct sk_buff *skb) if (skb_checksum_help(skb, 0)) goto out_kfree_skb; + spin_lock_prefetch(&dev->queue_lock); + /* Disable soft irqs for various locks below. Also * stops preemption for RCU. */ -- cgit v0.10.2 From 9356b8fc07dc126cd91d2b12f314d760ab48996e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 27 Sep 2005 15:23:16 -0700 Subject: [NET]: Reorder some hot fields of struct net_device Place them on separate cache lines in SMP to lower memory bouncing between multiple CPU accessing the device. - One part is mostly used on receive path (including eth_type_trans()) (poll_list, poll, quota, weight, last_rx, dev_addr, broadcast) - One part is mostly used on queue transmit path (qdisc) (queue_lock, qdisc, qdisc_sleeping, qdisc_list, tx_queue_len) - One part is mostly used on xmit path (device) (xmit_lock, xmit_lock_owner, priv, hard_start_xmit, trans_start) 'features' is placed outside of these hot points, in a location that may be shared by all cpus (because mostly read) name_hlist is moved close to name[IFNAMSIZ] to speedup __dev_get_by_name() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7c71790..368e4c8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -265,6 +265,8 @@ struct net_device * the interface. */ char name[IFNAMSIZ]; + /* device name hash chain */ + struct hlist_node name_hlist; /* * I/O specific fields @@ -292,6 +294,21 @@ struct net_device /* ------- Fields preinitialized in Space.c finish here ------- */ + /* Net device features */ + unsigned long features; +#define NETIF_F_SG 1 /* Scatter/gather IO. */ +#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */ +#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ +#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */ +#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */ +#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */ +#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */ +#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ +#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ +#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ +#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ +#define NETIF_F_LLTX 4096 /* LockLess TX */ + struct net_device *next_sched; /* Interface index. Unique device identifier */ @@ -316,9 +333,6 @@ struct net_device * will (read: may be cleaned up at will). */ - /* These may be needed for future network-power-down code. */ - unsigned long trans_start; /* Time (in jiffies) of last Tx */ - unsigned long last_rx; /* Time of last Rx */ unsigned short flags; /* interface flags (a la BSD) */ unsigned short gflags; @@ -328,15 +342,12 @@ struct net_device unsigned mtu; /* interface MTU value */ unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ - void *priv; /* pointer to private data */ struct net_device *master; /* Pointer to master device of a group, * which this device is member of. */ /* Interface address info. */ - unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ - unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */ unsigned char addr_len; /* hardware address length */ unsigned short dev_id; /* for shared network cards */ @@ -346,8 +357,6 @@ struct net_device int promiscuity; int allmulti; - int watchdog_timeo; - struct timer_list watchdog_timer; /* Protocol specific pointers */ @@ -358,32 +367,62 @@ struct net_device void *ec_ptr; /* Econet specific data */ void *ax25_ptr; /* AX.25 specific data */ - struct list_head poll_list; /* Link to poll list */ +/* + * Cache line mostly used on receive path (including eth_type_trans()) + */ + struct list_head poll_list ____cacheline_aligned_in_smp; + /* Link to poll list */ + + int (*poll) (struct net_device *dev, int *quota); int quota; int weight; + unsigned long last_rx; /* Time of last Rx */ + /* Interface address info used in eth_type_trans() */ + unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast + because most packets are unicast) */ + + unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ +/* + * Cache line mostly used on queue transmit path (qdisc) + */ + /* device queue lock */ + spinlock_t queue_lock ____cacheline_aligned_in_smp; struct Qdisc *qdisc; struct Qdisc *qdisc_sleeping; - struct Qdisc *qdisc_ingress; struct list_head qdisc_list; unsigned long tx_queue_len; /* Max frames per queue allowed */ /* ingress path synchronizer */ spinlock_t ingress_lock; + struct Qdisc *qdisc_ingress; + +/* + * One part is mostly used on xmit path (device) + */ /* hard_start_xmit synchronizer */ - spinlock_t xmit_lock; + spinlock_t xmit_lock ____cacheline_aligned_in_smp; /* cpu id of processor entered to hard_start_xmit or -1, if nobody entered there. */ int xmit_lock_owner; - /* device queue lock */ - spinlock_t queue_lock; + void *priv; /* pointer to private data */ + int (*hard_start_xmit) (struct sk_buff *skb, + struct net_device *dev); + /* These may be needed for future network-power-down code. */ + unsigned long trans_start; /* Time (in jiffies) of last Tx */ + + int watchdog_timeo; /* used by dev_watchdog() */ + struct timer_list watchdog_timer; + +/* + * refcnt is a very hot point, so align it on SMP + */ /* Number of references to this device */ - atomic_t refcnt; + atomic_t refcnt ____cacheline_aligned_in_smp; + /* delayed register/unregister */ struct list_head todo_list; - /* device name hash chain */ - struct hlist_node name_hlist; /* device index hash chain */ struct hlist_node index_hlist; @@ -396,21 +435,6 @@ struct net_device NETREG_RELEASED, /* called free_netdev */ } reg_state; - /* Net device features */ - unsigned long features; -#define NETIF_F_SG 1 /* Scatter/gather IO. */ -#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */ -#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ -#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */ -#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */ -#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */ -#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */ -#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ -#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ -#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ -#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */ -#define NETIF_F_LLTX 4096 /* LockLess TX */ - /* Called after device is detached from network. */ void (*uninit)(struct net_device *dev); /* Called after last user reference disappears. */ @@ -419,10 +443,7 @@ struct net_device /* Pointers to interface service routines. */ int (*open)(struct net_device *dev); int (*stop)(struct net_device *dev); - int (*hard_start_xmit) (struct sk_buff *skb, - struct net_device *dev); #define HAVE_NETDEV_POLL - int (*poll) (struct net_device *dev, int *quota); int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, -- cgit v0.10.2 From a79af59efd20990473d579b1d8d70bb120f0920c Mon Sep 17 00:00:00 2001 From: Frank Filz Date: Tue, 27 Sep 2005 15:23:38 -0700 Subject: [NET]: Fix module reference counts for loadable protocol modules I have been experimenting with loadable protocol modules, and ran into several issues with module reference counting. The first issue was that __module_get failed at the BUG_ON check at the top of the routine (checking that my module reference count was not zero) when I created the first socket. When sk_alloc() is called, my module reference count was still 0. When I looked at why sctp didn't have this problem, I discovered that sctp creates a control socket during module init (when the module ref count is not 0), which keeps the reference count non-zero. This section has been updated to address the point Stephen raised about checking the return value of try_module_get(). The next problem arose when my socket init routine returned an error. This resulted in my module reference count being decremented below 0. My socket ops->release routine was also being called. The issue here is that sock_release() calls the ops->release routine and decrements the ref count if sock->ops is not NULL. Since the socket probably didn't get correctly initialized, this should not be done, so we will set sock->ops to NULL because we will not call try_module_get(). While searching for another bug, I also noticed that sys_accept() has a possibility of doing a module_put() when it did not do an __module_get so I re-ordered the call to security_socket_accept(). Signed-off-by: Frank Filz Signed-off-by: David S. Miller diff --git a/net/core/sock.c b/net/core/sock.c index ac63b56..928d2a1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -660,16 +660,20 @@ struct sock *sk_alloc(int family, unsigned int __nocast priority, sock_lock_init(sk); } - if (security_sk_alloc(sk, family, priority)) { - if (slab != NULL) - kmem_cache_free(slab, sk); - else - kfree(sk); - sk = NULL; - } else - __module_get(prot->owner); + if (security_sk_alloc(sk, family, priority)) + goto out_free; + + if (!try_module_get(prot->owner)) + goto out_free; } return sk; + +out_free: + if (slab != NULL) + kmem_cache_free(slab, sk); + else + kfree(sk); + return NULL; } void sk_free(struct sock *sk) diff --git a/net/socket.c b/net/socket.c index dbd1a68..3145103 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1145,8 +1145,11 @@ static int __sock_create(int family, int type, int protocol, struct socket **res if (!try_module_get(net_families[family]->owner)) goto out_release; - if ((err = net_families[family]->create(sock, protocol)) < 0) + if ((err = net_families[family]->create(sock, protocol)) < 0) { + sock->ops = NULL; goto out_module_put; + } + /* * Now to bump the refcnt of the [loadable] module that owns this * socket at sock_release time we decrement its refcnt. @@ -1360,16 +1363,16 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ newsock->type = sock->type; newsock->ops = sock->ops; - err = security_socket_accept(sock, newsock); - if (err) - goto out_release; - /* * We don't need try_module_get here, as the listening socket (sock) * has the protocol module (sock->ops->owner) held. */ __module_get(newsock->ops->owner); + err = security_socket_accept(sock, newsock); + if (err) + goto out_release; + err = sock->ops->accept(sock, newsock, sock->file->f_flags); if (err < 0) goto out_release; -- cgit v0.10.2 From 1f26dac32057baaf67d10b45c6b5277db862911d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 15:24:13 -0700 Subject: [NET]: Add Sun Cassini driver. Written by Adrian Sun (asun@darksunrising.com). Ported to 2.6.x by Tom 'spot' Callaway . Further cleaned up and integrated by David S. Miller Signed-off-by: David S. Miller diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 96f14ab..2a908c4 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -548,6 +548,14 @@ config SUNGEM Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also . +config CASSINI + tristate "Sun Cassini support" + depends on NET_ETHERNET && PCI + select CRC32 + help + Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also + + config NET_VENDOR_3COM bool "3COM cards" depends on NET_ETHERNET && (ISA || EISA || MCA || PCI) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 8645c84..8aeec9f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SUNQE) += sunqe.o obj-$(CONFIG_SUNBMAC) += sunbmac.o obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o +obj-$(CONFIG_CASSINI) += cassini.o obj-$(CONFIG_MACE) += mace.o obj-$(CONFIG_BMAC) += bmac.o diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c new file mode 100644 index 0000000..69cb368 --- /dev/null +++ b/drivers/net/cassini.c @@ -0,0 +1,5311 @@ +/* cassini.c: Sun Microsystems Cassini(+) ethernet driver. + * + * Copyright (C) 2004 Sun Microsystems Inc. + * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com) + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * This driver uses the sungem driver (c) David Miller + * (davem@redhat.com) as its basis. + * + * The cassini chip has a number of features that distinguish it from + * the gem chip: + * 4 transmit descriptor rings that are used for either QoS (VLAN) or + * load balancing (non-VLAN mode) + * batching of multiple packets + * multiple CPU dispatching + * page-based RX descriptor engine with separate completion rings + * Gigabit support (GMII and PCS interface) + * MIF link up/down detection works + * + * RX is handled by page sized buffers that are attached as fragments to + * the skb. here's what's done: + * -- driver allocates pages at a time and keeps reference counts + * on them. + * -- the upper protocol layers assume that the header is in the skb + * itself. as a result, cassini will copy a small amount (64 bytes) + * to make them happy. + * -- driver appends the rest of the data pages as frags to skbuffs + * and increments the reference count + * -- on page reclamation, the driver swaps the page with a spare page. + * if that page is still in use, it frees its reference to that page, + * and allocates a new page for use. otherwise, it just recycles the + * the page. + * + * NOTE: cassini can parse the header. however, it's not worth it + * as long as the network stack requires a header copy. + * + * TX has 4 queues. currently these queues are used in a round-robin + * fashion for load balancing. They can also be used for QoS. for that + * to work, however, QoS information needs to be exposed down to the driver + * level so that subqueues get targetted to particular transmit rings. + * alternatively, the queues can be configured via use of the all-purpose + * ioctl. + * + * RX DATA: the rx completion ring has all the info, but the rx desc + * ring has all of the data. RX can conceivably come in under multiple + * interrupts, but the INT# assignment needs to be set up properly by + * the BIOS and conveyed to the driver. PCI BIOSes don't know how to do + * that. also, the two descriptor rings are designed to distinguish between + * encrypted and non-encrypted packets, but we use them for buffering + * instead. + * + * by default, the selective clear mask is set up to process rx packets. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define cas_page_map(x) kmap_atomic((x), KM_SKB_DATA_SOFTIRQ) +#define cas_page_unmap(x) kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ) +#define CAS_NCPUS num_online_cpus() + +#if defined(CONFIG_CASSINI_NAPI) && defined(HAVE_NETDEV_POLL) +#define USE_NAPI +#define cas_skb_release(x) netif_receive_skb(x) +#else +#define cas_skb_release(x) netif_rx(x) +#endif + +/* select which firmware to use */ +#define USE_HP_WORKAROUND +#define HP_WORKAROUND_DEFAULT /* select which firmware to use as default */ +#define CAS_HP_ALT_FIRMWARE cas_prog_null /* alternate firmware */ + +#include "cassini.h" + +#define USE_TX_COMPWB /* use completion writeback registers */ +#define USE_CSMA_CD_PROTO /* standard CSMA/CD */ +#define USE_RX_BLANK /* hw interrupt mitigation */ +#undef USE_ENTROPY_DEV /* don't test for entropy device */ + +/* NOTE: these aren't useable unless PCI interrupts can be assigned. + * also, we need to make cp->lock finer-grained. + */ +#undef USE_PCI_INTB +#undef USE_PCI_INTC +#undef USE_PCI_INTD +#undef USE_QOS + +#undef USE_VPD_DEBUG /* debug vpd information if defined */ + +/* rx processing options */ +#define USE_PAGE_ORDER /* specify to allocate large rx pages */ +#define RX_DONT_BATCH 0 /* if 1, don't batch flows */ +#define RX_COPY_ALWAYS 0 /* if 0, use frags */ +#define RX_COPY_MIN 64 /* copy a little to make upper layers happy */ +#undef RX_COUNT_BUFFERS /* define to calculate RX buffer stats */ + +#define DRV_MODULE_NAME "cassini" +#define PFX DRV_MODULE_NAME ": " +#define DRV_MODULE_VERSION "1.4" +#define DRV_MODULE_RELDATE "1 July 2004" + +#define CAS_DEF_MSG_ENABLE \ + (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_TIMER | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR) + +/* length of time before we decide the hardware is borked, + * and dev->tx_timeout() should be called to fix the problem + */ +#define CAS_TX_TIMEOUT (HZ) +#define CAS_LINK_TIMEOUT (22*HZ/10) +#define CAS_LINK_FAST_TIMEOUT (1) + +/* timeout values for state changing. these specify the number + * of 10us delays to be used before giving up. + */ +#define STOP_TRIES_PHY 1000 +#define STOP_TRIES 5000 + +/* specify a minimum frame size to deal with some fifo issues + * max mtu == 2 * page size - ethernet header - 64 - swivel = + * 2 * page_size - 0x50 + */ +#define CAS_MIN_FRAME 97 +#define CAS_1000MB_MIN_FRAME 255 +#define CAS_MIN_MTU 60 +#define CAS_MAX_MTU min(((cp->page_size << 1) - 0x50), 9000) + +#if 1 +/* + * Eliminate these and use separate atomic counters for each, to + * avoid a race condition. + */ +#else +#define CAS_RESET_MTU 1 +#define CAS_RESET_ALL 2 +#define CAS_RESET_SPARE 3 +#endif + +static char version[] __devinitdata = + DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + +MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)"); +MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver"); +MODULE_LICENSE("GPL"); +MODULE_PARM(cassini_debug, "i"); +MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value"); +MODULE_PARM(link_mode, "i"); +MODULE_PARM_DESC(link_mode, "default link mode"); + +/* + * Work around for a PCS bug in which the link goes down due to the chip + * being confused and never showing a link status of "up." + */ +#define DEFAULT_LINKDOWN_TIMEOUT 5 +/* + * Value in seconds, for user input. + */ +static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT; +MODULE_PARM(linkdown_timeout, "i"); +MODULE_PARM_DESC(linkdown_timeout, +"min reset interval in sec. for PCS linkdown issue; disabled if not positive"); + +/* + * value in 'ticks' (units used by jiffies). Set when we init the + * module because 'HZ' in actually a function call on some flavors of + * Linux. This will default to DEFAULT_LINKDOWN_TIMEOUT * HZ. + */ +static int link_transition_timeout; + + +static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */ +static int link_mode; + +static u16 link_modes[] __devinitdata = { + BMCR_ANENABLE, /* 0 : autoneg */ + 0, /* 1 : 10bt half duplex */ + BMCR_SPEED100, /* 2 : 100bt half duplex */ + BMCR_FULLDPLX, /* 3 : 10bt full duplex */ + BMCR_SPEED100|BMCR_FULLDPLX, /* 4 : 100bt full duplex */ + CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */ +}; + +static struct pci_device_id cas_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, cas_pci_tbl); + +static void cas_set_link_modes(struct cas *cp); + +static inline void cas_lock_tx(struct cas *cp) +{ + int i; + + for (i = 0; i < N_TX_RINGS; i++) + spin_lock(&cp->tx_lock[i]); +} + +static inline void cas_lock_all(struct cas *cp) +{ + spin_lock_irq(&cp->lock); + cas_lock_tx(cp); +} + +/* WTZ: QA was finding deadlock problems with the previous + * versions after long test runs with multiple cards per machine. + * See if replacing cas_lock_all with safer versions helps. The + * symptoms QA is reporting match those we'd expect if interrupts + * aren't being properly restored, and we fixed a previous deadlock + * with similar symptoms by using save/restore versions in other + * places. + */ +#define cas_lock_all_save(cp, flags) \ +do { \ + struct cas *xxxcp = (cp); \ + spin_lock_irqsave(&xxxcp->lock, flags); \ + cas_lock_tx(xxxcp); \ +} while (0) + +static inline void cas_unlock_tx(struct cas *cp) +{ + int i; + + for (i = N_TX_RINGS; i > 0; i--) + spin_unlock(&cp->tx_lock[i - 1]); +} + +static inline void cas_unlock_all(struct cas *cp) +{ + cas_unlock_tx(cp); + spin_unlock_irq(&cp->lock); +} + +#define cas_unlock_all_restore(cp, flags) \ +do { \ + struct cas *xxxcp = (cp); \ + cas_unlock_tx(xxxcp); \ + spin_unlock_irqrestore(&xxxcp->lock, flags); \ +} while (0) + +static void cas_disable_irq(struct cas *cp, const int ring) +{ + /* Make sure we won't get any more interrupts */ + if (ring == 0) { + writel(0xFFFFFFFF, cp->regs + REG_INTR_MASK); + return; + } + + /* disable completion interrupts and selectively mask */ + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + switch (ring) { +#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD) +#ifdef USE_PCI_INTB + case 1: +#endif +#ifdef USE_PCI_INTC + case 2: +#endif +#ifdef USE_PCI_INTD + case 3: +#endif + writel(INTRN_MASK_CLEAR_ALL | INTRN_MASK_RX_EN, + cp->regs + REG_PLUS_INTRN_MASK(ring)); + break; +#endif + default: + writel(INTRN_MASK_CLEAR_ALL, cp->regs + + REG_PLUS_INTRN_MASK(ring)); + break; + } + } +} + +static inline void cas_mask_intr(struct cas *cp) +{ + int i; + + for (i = 0; i < N_RX_COMP_RINGS; i++) + cas_disable_irq(cp, i); +} + +static void cas_enable_irq(struct cas *cp, const int ring) +{ + if (ring == 0) { /* all but TX_DONE */ + writel(INTR_TX_DONE, cp->regs + REG_INTR_MASK); + return; + } + + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + switch (ring) { +#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD) +#ifdef USE_PCI_INTB + case 1: +#endif +#ifdef USE_PCI_INTC + case 2: +#endif +#ifdef USE_PCI_INTD + case 3: +#endif + writel(INTRN_MASK_RX_EN, cp->regs + + REG_PLUS_INTRN_MASK(ring)); + break; +#endif + default: + break; + } + } +} + +static inline void cas_unmask_intr(struct cas *cp) +{ + int i; + + for (i = 0; i < N_RX_COMP_RINGS; i++) + cas_enable_irq(cp, i); +} + +static inline void cas_entropy_gather(struct cas *cp) +{ +#ifdef USE_ENTROPY_DEV + if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0) + return; + + batch_entropy_store(readl(cp->regs + REG_ENTROPY_IV), + readl(cp->regs + REG_ENTROPY_IV), + sizeof(uint64_t)*8); +#endif +} + +static inline void cas_entropy_reset(struct cas *cp) +{ +#ifdef USE_ENTROPY_DEV + if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0) + return; + + writel(BIM_LOCAL_DEV_PAD | BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_EXT, + cp->regs + REG_BIM_LOCAL_DEV_EN); + writeb(ENTROPY_RESET_STC_MODE, cp->regs + REG_ENTROPY_RESET); + writeb(0x55, cp->regs + REG_ENTROPY_RAND_REG); + + /* if we read back 0x0, we don't have an entropy device */ + if (readb(cp->regs + REG_ENTROPY_RAND_REG) == 0) + cp->cas_flags &= ~CAS_FLAG_ENTROPY_DEV; +#endif +} + +/* access to the phy. the following assumes that we've initialized the MIF to + * be in frame rather than bit-bang mode + */ +static u16 cas_phy_read(struct cas *cp, int reg) +{ + u32 cmd; + int limit = STOP_TRIES_PHY; + + cmd = MIF_FRAME_ST | MIF_FRAME_OP_READ; + cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr); + cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg); + cmd |= MIF_FRAME_TURN_AROUND_MSB; + writel(cmd, cp->regs + REG_MIF_FRAME); + + /* poll for completion */ + while (limit-- > 0) { + udelay(10); + cmd = readl(cp->regs + REG_MIF_FRAME); + if (cmd & MIF_FRAME_TURN_AROUND_LSB) + return (cmd & MIF_FRAME_DATA_MASK); + } + return 0xFFFF; /* -1 */ +} + +static int cas_phy_write(struct cas *cp, int reg, u16 val) +{ + int limit = STOP_TRIES_PHY; + u32 cmd; + + cmd = MIF_FRAME_ST | MIF_FRAME_OP_WRITE; + cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr); + cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg); + cmd |= MIF_FRAME_TURN_AROUND_MSB; + cmd |= val & MIF_FRAME_DATA_MASK; + writel(cmd, cp->regs + REG_MIF_FRAME); + + /* poll for completion */ + while (limit-- > 0) { + udelay(10); + cmd = readl(cp->regs + REG_MIF_FRAME); + if (cmd & MIF_FRAME_TURN_AROUND_LSB) + return 0; + } + return -1; +} + +static void cas_phy_powerup(struct cas *cp) +{ + u16 ctl = cas_phy_read(cp, MII_BMCR); + + if ((ctl & BMCR_PDOWN) == 0) + return; + ctl &= ~BMCR_PDOWN; + cas_phy_write(cp, MII_BMCR, ctl); +} + +static void cas_phy_powerdown(struct cas *cp) +{ + u16 ctl = cas_phy_read(cp, MII_BMCR); + + if (ctl & BMCR_PDOWN) + return; + ctl |= BMCR_PDOWN; + cas_phy_write(cp, MII_BMCR, ctl); +} + +/* cp->lock held. note: the last put_page will free the buffer */ +static int cas_page_free(struct cas *cp, cas_page_t *page) +{ + pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size, + PCI_DMA_FROMDEVICE); + __free_pages(page->buffer, cp->page_order); + kfree(page); + return 0; +} + +#ifdef RX_COUNT_BUFFERS +#define RX_USED_ADD(x, y) ((x)->used += (y)) +#define RX_USED_SET(x, y) ((x)->used = (y)) +#else +#define RX_USED_ADD(x, y) +#define RX_USED_SET(x, y) +#endif + +/* local page allocation routines for the receive buffers. jumbo pages + * require at least 8K contiguous and 8K aligned buffers. + */ +static cas_page_t *cas_page_alloc(struct cas *cp, const int flags) +{ + cas_page_t *page; + + page = kmalloc(sizeof(cas_page_t), flags); + if (!page) + return NULL; + + INIT_LIST_HEAD(&page->list); + RX_USED_SET(page, 0); + page->buffer = alloc_pages(flags, cp->page_order); + if (!page->buffer) + goto page_err; + page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0, + cp->page_size, PCI_DMA_FROMDEVICE); + return page; + +page_err: + kfree(page); + return NULL; +} + +/* initialize spare pool of rx buffers, but allocate during the open */ +static void cas_spare_init(struct cas *cp) +{ + spin_lock(&cp->rx_inuse_lock); + INIT_LIST_HEAD(&cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); + + spin_lock(&cp->rx_spare_lock); + INIT_LIST_HEAD(&cp->rx_spare_list); + cp->rx_spares_needed = RX_SPARE_COUNT; + spin_unlock(&cp->rx_spare_lock); +} + +/* used on close. free all the spare buffers. */ +static void cas_spare_free(struct cas *cp) +{ + struct list_head list, *elem, *tmp; + + /* free spare buffers */ + INIT_LIST_HEAD(&list); + spin_lock(&cp->rx_spare_lock); + list_splice(&cp->rx_spare_list, &list); + INIT_LIST_HEAD(&cp->rx_spare_list); + spin_unlock(&cp->rx_spare_lock); + list_for_each_safe(elem, tmp, &list) { + cas_page_free(cp, list_entry(elem, cas_page_t, list)); + } + + INIT_LIST_HEAD(&list); +#if 1 + /* + * Looks like Adrian had protected this with a different + * lock than used everywhere else to manipulate this list. + */ + spin_lock(&cp->rx_inuse_lock); + list_splice(&cp->rx_inuse_list, &list); + INIT_LIST_HEAD(&cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); +#else + spin_lock(&cp->rx_spare_lock); + list_splice(&cp->rx_inuse_list, &list); + INIT_LIST_HEAD(&cp->rx_inuse_list); + spin_unlock(&cp->rx_spare_lock); +#endif + list_for_each_safe(elem, tmp, &list) { + cas_page_free(cp, list_entry(elem, cas_page_t, list)); + } +} + +/* replenish spares if needed */ +static void cas_spare_recover(struct cas *cp, const int flags) +{ + struct list_head list, *elem, *tmp; + int needed, i; + + /* check inuse list. if we don't need any more free buffers, + * just free it + */ + + /* make a local copy of the list */ + INIT_LIST_HEAD(&list); + spin_lock(&cp->rx_inuse_lock); + list_splice(&cp->rx_inuse_list, &list); + INIT_LIST_HEAD(&cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); + + list_for_each_safe(elem, tmp, &list) { + cas_page_t *page = list_entry(elem, cas_page_t, list); + + if (page_count(page->buffer) > 1) + continue; + + list_del(elem); + spin_lock(&cp->rx_spare_lock); + if (cp->rx_spares_needed > 0) { + list_add(elem, &cp->rx_spare_list); + cp->rx_spares_needed--; + spin_unlock(&cp->rx_spare_lock); + } else { + spin_unlock(&cp->rx_spare_lock); + cas_page_free(cp, page); + } + } + + /* put any inuse buffers back on the list */ + if (!list_empty(&list)) { + spin_lock(&cp->rx_inuse_lock); + list_splice(&list, &cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); + } + + spin_lock(&cp->rx_spare_lock); + needed = cp->rx_spares_needed; + spin_unlock(&cp->rx_spare_lock); + if (!needed) + return; + + /* we still need spares, so try to allocate some */ + INIT_LIST_HEAD(&list); + i = 0; + while (i < needed) { + cas_page_t *spare = cas_page_alloc(cp, flags); + if (!spare) + break; + list_add(&spare->list, &list); + i++; + } + + spin_lock(&cp->rx_spare_lock); + list_splice(&list, &cp->rx_spare_list); + cp->rx_spares_needed -= i; + spin_unlock(&cp->rx_spare_lock); +} + +/* pull a page from the list. */ +static cas_page_t *cas_page_dequeue(struct cas *cp) +{ + struct list_head *entry; + int recover; + + spin_lock(&cp->rx_spare_lock); + if (list_empty(&cp->rx_spare_list)) { + /* try to do a quick recovery */ + spin_unlock(&cp->rx_spare_lock); + cas_spare_recover(cp, GFP_ATOMIC); + spin_lock(&cp->rx_spare_lock); + if (list_empty(&cp->rx_spare_list)) { + if (netif_msg_rx_err(cp)) + printk(KERN_ERR "%s: no spare buffers " + "available.\n", cp->dev->name); + spin_unlock(&cp->rx_spare_lock); + return NULL; + } + } + + entry = cp->rx_spare_list.next; + list_del(entry); + recover = ++cp->rx_spares_needed; + spin_unlock(&cp->rx_spare_lock); + + /* trigger the timer to do the recovery */ + if ((recover & (RX_SPARE_RECOVER_VAL - 1)) == 0) { +#if 1 + atomic_inc(&cp->reset_task_pending); + atomic_inc(&cp->reset_task_pending_spare); + schedule_work(&cp->reset_task); +#else + atomic_set(&cp->reset_task_pending, CAS_RESET_SPARE); + schedule_work(&cp->reset_task); +#endif + } + return list_entry(entry, cas_page_t, list); +} + + +static void cas_mif_poll(struct cas *cp, const int enable) +{ + u32 cfg; + + cfg = readl(cp->regs + REG_MIF_CFG); + cfg &= (MIF_CFG_MDIO_0 | MIF_CFG_MDIO_1); + + if (cp->phy_type & CAS_PHY_MII_MDIO1) + cfg |= MIF_CFG_PHY_SELECT; + + /* poll and interrupt on link status change. */ + if (enable) { + cfg |= MIF_CFG_POLL_EN; + cfg |= CAS_BASE(MIF_CFG_POLL_REG, MII_BMSR); + cfg |= CAS_BASE(MIF_CFG_POLL_PHY, cp->phy_addr); + } + writel((enable) ? ~(BMSR_LSTATUS | BMSR_ANEGCOMPLETE) : 0xFFFF, + cp->regs + REG_MIF_MASK); + writel(cfg, cp->regs + REG_MIF_CFG); +} + +/* Must be invoked under cp->lock */ +static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep) +{ + u16 ctl; +#if 1 + int lcntl; + int changed = 0; + int oldstate = cp->lstate; + int link_was_not_down = !(oldstate == link_down); +#endif + /* Setup link parameters */ + if (!ep) + goto start_aneg; + lcntl = cp->link_cntl; + if (ep->autoneg == AUTONEG_ENABLE) + cp->link_cntl = BMCR_ANENABLE; + else { + cp->link_cntl = 0; + if (ep->speed == SPEED_100) + cp->link_cntl |= BMCR_SPEED100; + else if (ep->speed == SPEED_1000) + cp->link_cntl |= CAS_BMCR_SPEED1000; + if (ep->duplex == DUPLEX_FULL) + cp->link_cntl |= BMCR_FULLDPLX; + } +#if 1 + changed = (lcntl != cp->link_cntl); +#endif +start_aneg: + if (cp->lstate == link_up) { + printk(KERN_INFO "%s: PCS link down.\n", + cp->dev->name); + } else { + if (changed) { + printk(KERN_INFO "%s: link configuration changed\n", + cp->dev->name); + } + } + cp->lstate = link_down; + cp->link_transition = LINK_TRANSITION_LINK_DOWN; + if (!cp->hw_running) + return; +#if 1 + /* + * WTZ: If the old state was link_up, we turn off the carrier + * to replicate everything we do elsewhere on a link-down + * event when we were already in a link-up state.. + */ + if (oldstate == link_up) + netif_carrier_off(cp->dev); + if (changed && link_was_not_down) { + /* + * WTZ: This branch will simply schedule a full reset after + * we explicitly changed link modes in an ioctl. See if this + * fixes the link-problems we were having for forced mode. + */ + atomic_inc(&cp->reset_task_pending); + atomic_inc(&cp->reset_task_pending_all); + schedule_work(&cp->reset_task); + cp->timer_ticks = 0; + mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT); + return; + } +#endif + if (cp->phy_type & CAS_PHY_SERDES) { + u32 val = readl(cp->regs + REG_PCS_MII_CTRL); + + if (cp->link_cntl & BMCR_ANENABLE) { + val |= (PCS_MII_RESTART_AUTONEG | PCS_MII_AUTONEG_EN); + cp->lstate = link_aneg; + } else { + if (cp->link_cntl & BMCR_FULLDPLX) + val |= PCS_MII_CTRL_DUPLEX; + val &= ~PCS_MII_AUTONEG_EN; + cp->lstate = link_force_ok; + } + cp->link_transition = LINK_TRANSITION_LINK_CONFIG; + writel(val, cp->regs + REG_PCS_MII_CTRL); + + } else { + cas_mif_poll(cp, 0); + ctl = cas_phy_read(cp, MII_BMCR); + ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | + CAS_BMCR_SPEED1000 | BMCR_ANENABLE); + ctl |= cp->link_cntl; + if (ctl & BMCR_ANENABLE) { + ctl |= BMCR_ANRESTART; + cp->lstate = link_aneg; + } else { + cp->lstate = link_force_ok; + } + cp->link_transition = LINK_TRANSITION_LINK_CONFIG; + cas_phy_write(cp, MII_BMCR, ctl); + cas_mif_poll(cp, 1); + } + + cp->timer_ticks = 0; + mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT); +} + +/* Must be invoked under cp->lock. */ +static int cas_reset_mii_phy(struct cas *cp) +{ + int limit = STOP_TRIES_PHY; + u16 val; + + cas_phy_write(cp, MII_BMCR, BMCR_RESET); + udelay(100); + while (limit--) { + val = cas_phy_read(cp, MII_BMCR); + if ((val & BMCR_RESET) == 0) + break; + udelay(10); + } + return (limit <= 0); +} + +static void cas_saturn_firmware_load(struct cas *cp) +{ + cas_saturn_patch_t *patch = cas_saturn_patch; + + cas_phy_powerdown(cp); + + /* expanded memory access mode */ + cas_phy_write(cp, DP83065_MII_MEM, 0x0); + + /* pointer configuration for new firmware */ + cas_phy_write(cp, DP83065_MII_REGE, 0x8ff9); + cas_phy_write(cp, DP83065_MII_REGD, 0xbd); + cas_phy_write(cp, DP83065_MII_REGE, 0x8ffa); + cas_phy_write(cp, DP83065_MII_REGD, 0x82); + cas_phy_write(cp, DP83065_MII_REGE, 0x8ffb); + cas_phy_write(cp, DP83065_MII_REGD, 0x0); + cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc); + cas_phy_write(cp, DP83065_MII_REGD, 0x39); + + /* download new firmware */ + cas_phy_write(cp, DP83065_MII_MEM, 0x1); + cas_phy_write(cp, DP83065_MII_REGE, patch->addr); + while (patch->addr) { + cas_phy_write(cp, DP83065_MII_REGD, patch->val); + patch++; + } + + /* enable firmware */ + cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8); + cas_phy_write(cp, DP83065_MII_REGD, 0x1); +} + + +/* phy initialization */ +static void cas_phy_init(struct cas *cp) +{ + u16 val; + + /* if we're in MII/GMII mode, set up phy */ + if (CAS_PHY_MII(cp->phy_type)) { + writel(PCS_DATAPATH_MODE_MII, + cp->regs + REG_PCS_DATAPATH_MODE); + + cas_mif_poll(cp, 0); + cas_reset_mii_phy(cp); /* take out of isolate mode */ + + if (PHY_LUCENT_B0 == cp->phy_id) { + /* workaround link up/down issue with lucent */ + cas_phy_write(cp, LUCENT_MII_REG, 0x8000); + cas_phy_write(cp, MII_BMCR, 0x00f1); + cas_phy_write(cp, LUCENT_MII_REG, 0x0); + + } else if (PHY_BROADCOM_B0 == (cp->phy_id & 0xFFFFFFFC)) { + /* workarounds for broadcom phy */ + cas_phy_write(cp, BROADCOM_MII_REG8, 0x0C20); + cas_phy_write(cp, BROADCOM_MII_REG7, 0x0012); + cas_phy_write(cp, BROADCOM_MII_REG5, 0x1804); + cas_phy_write(cp, BROADCOM_MII_REG7, 0x0013); + cas_phy_write(cp, BROADCOM_MII_REG5, 0x1204); + cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006); + cas_phy_write(cp, BROADCOM_MII_REG5, 0x0132); + cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006); + cas_phy_write(cp, BROADCOM_MII_REG5, 0x0232); + cas_phy_write(cp, BROADCOM_MII_REG7, 0x201F); + cas_phy_write(cp, BROADCOM_MII_REG5, 0x0A20); + + } else if (PHY_BROADCOM_5411 == cp->phy_id) { + val = cas_phy_read(cp, BROADCOM_MII_REG4); + val = cas_phy_read(cp, BROADCOM_MII_REG4); + if (val & 0x0080) { + /* link workaround */ + cas_phy_write(cp, BROADCOM_MII_REG4, + val & ~0x0080); + } + + } else if (cp->cas_flags & CAS_FLAG_SATURN) { + writel((cp->phy_type & CAS_PHY_MII_MDIO0) ? + SATURN_PCFG_FSI : 0x0, + cp->regs + REG_SATURN_PCFG); + + /* load firmware to address 10Mbps auto-negotiation + * issue. NOTE: this will need to be changed if the + * default firmware gets fixed. + */ + if (PHY_NS_DP83065 == cp->phy_id) { + cas_saturn_firmware_load(cp); + } + cas_phy_powerup(cp); + } + + /* advertise capabilities */ + val = cas_phy_read(cp, MII_BMCR); + val &= ~BMCR_ANENABLE; + cas_phy_write(cp, MII_BMCR, val); + udelay(10); + + cas_phy_write(cp, MII_ADVERTISE, + cas_phy_read(cp, MII_ADVERTISE) | + (ADVERTISE_10HALF | ADVERTISE_10FULL | + ADVERTISE_100HALF | ADVERTISE_100FULL | + CAS_ADVERTISE_PAUSE | + CAS_ADVERTISE_ASYM_PAUSE)); + + if (cp->cas_flags & CAS_FLAG_1000MB_CAP) { + /* make sure that we don't advertise half + * duplex to avoid a chip issue + */ + val = cas_phy_read(cp, CAS_MII_1000_CTRL); + val &= ~CAS_ADVERTISE_1000HALF; + val |= CAS_ADVERTISE_1000FULL; + cas_phy_write(cp, CAS_MII_1000_CTRL, val); + } + + } else { + /* reset pcs for serdes */ + u32 val; + int limit; + + writel(PCS_DATAPATH_MODE_SERDES, + cp->regs + REG_PCS_DATAPATH_MODE); + + /* enable serdes pins on saturn */ + if (cp->cas_flags & CAS_FLAG_SATURN) + writel(0, cp->regs + REG_SATURN_PCFG); + + /* Reset PCS unit. */ + val = readl(cp->regs + REG_PCS_MII_CTRL); + val |= PCS_MII_RESET; + writel(val, cp->regs + REG_PCS_MII_CTRL); + + limit = STOP_TRIES; + while (limit-- > 0) { + udelay(10); + if ((readl(cp->regs + REG_PCS_MII_CTRL) & + PCS_MII_RESET) == 0) + break; + } + if (limit <= 0) + printk(KERN_WARNING "%s: PCS reset bit would not " + "clear [%08x].\n", cp->dev->name, + readl(cp->regs + REG_PCS_STATE_MACHINE)); + + /* Make sure PCS is disabled while changing advertisement + * configuration. + */ + writel(0x0, cp->regs + REG_PCS_CFG); + + /* Advertise all capabilities except half-duplex. */ + val = readl(cp->regs + REG_PCS_MII_ADVERT); + val &= ~PCS_MII_ADVERT_HD; + val |= (PCS_MII_ADVERT_FD | PCS_MII_ADVERT_SYM_PAUSE | + PCS_MII_ADVERT_ASYM_PAUSE); + writel(val, cp->regs + REG_PCS_MII_ADVERT); + + /* enable PCS */ + writel(PCS_CFG_EN, cp->regs + REG_PCS_CFG); + + /* pcs workaround: enable sync detect */ + writel(PCS_SERDES_CTRL_SYNCD_EN, + cp->regs + REG_PCS_SERDES_CTRL); + } +} + + +static int cas_pcs_link_check(struct cas *cp) +{ + u32 stat, state_machine; + int retval = 0; + + /* The link status bit latches on zero, so you must + * read it twice in such a case to see a transition + * to the link being up. + */ + stat = readl(cp->regs + REG_PCS_MII_STATUS); + if ((stat & PCS_MII_STATUS_LINK_STATUS) == 0) + stat = readl(cp->regs + REG_PCS_MII_STATUS); + + /* The remote-fault indication is only valid + * when autoneg has completed. + */ + if ((stat & (PCS_MII_STATUS_AUTONEG_COMP | + PCS_MII_STATUS_REMOTE_FAULT)) == + (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) { + if (netif_msg_link(cp)) + printk(KERN_INFO "%s: PCS RemoteFault\n", + cp->dev->name); + } + + /* work around link detection issue by querying the PCS state + * machine directly. + */ + state_machine = readl(cp->regs + REG_PCS_STATE_MACHINE); + if ((state_machine & PCS_SM_LINK_STATE_MASK) != SM_LINK_STATE_UP) { + stat &= ~PCS_MII_STATUS_LINK_STATUS; + } else if (state_machine & PCS_SM_WORD_SYNC_STATE_MASK) { + stat |= PCS_MII_STATUS_LINK_STATUS; + } + + if (stat & PCS_MII_STATUS_LINK_STATUS) { + if (cp->lstate != link_up) { + if (cp->opened) { + cp->lstate = link_up; + cp->link_transition = LINK_TRANSITION_LINK_UP; + + cas_set_link_modes(cp); + netif_carrier_on(cp->dev); + } + } + } else if (cp->lstate == link_up) { + cp->lstate = link_down; + if (link_transition_timeout != 0 && + cp->link_transition != LINK_TRANSITION_REQUESTED_RESET && + !cp->link_transition_jiffies_valid) { + /* + * force a reset, as a workaround for the + * link-failure problem. May want to move this to a + * point a bit earlier in the sequence. If we had + * generated a reset a short time ago, we'll wait for + * the link timer to check the status until a + * timer expires (link_transistion_jiffies_valid is + * true when the timer is running.) Instead of using + * a system timer, we just do a check whenever the + * link timer is running - this clears the flag after + * a suitable delay. + */ + retval = 1; + cp->link_transition = LINK_TRANSITION_REQUESTED_RESET; + cp->link_transition_jiffies = jiffies; + cp->link_transition_jiffies_valid = 1; + } else { + cp->link_transition = LINK_TRANSITION_ON_FAILURE; + } + netif_carrier_off(cp->dev); + if (cp->opened && netif_msg_link(cp)) { + printk(KERN_INFO "%s: PCS link down.\n", + cp->dev->name); + } + + /* Cassini only: if you force a mode, there can be + * sync problems on link down. to fix that, the following + * things need to be checked: + * 1) read serialink state register + * 2) read pcs status register to verify link down. + * 3) if link down and serial link == 0x03, then you need + * to global reset the chip. + */ + if ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0) { + /* should check to see if we're in a forced mode */ + stat = readl(cp->regs + REG_PCS_SERDES_STATE); + if (stat == 0x03) + return 1; + } + } else if (cp->lstate == link_down) { + if (link_transition_timeout != 0 && + cp->link_transition != LINK_TRANSITION_REQUESTED_RESET && + !cp->link_transition_jiffies_valid) { + /* force a reset, as a workaround for the + * link-failure problem. May want to move + * this to a point a bit earlier in the + * sequence. + */ + retval = 1; + cp->link_transition = LINK_TRANSITION_REQUESTED_RESET; + cp->link_transition_jiffies = jiffies; + cp->link_transition_jiffies_valid = 1; + } else { + cp->link_transition = LINK_TRANSITION_STILL_FAILED; + } + } + + return retval; +} + +static int cas_pcs_interrupt(struct net_device *dev, + struct cas *cp, u32 status) +{ + u32 stat = readl(cp->regs + REG_PCS_INTR_STATUS); + + if ((stat & PCS_INTR_STATUS_LINK_CHANGE) == 0) + return 0; + return cas_pcs_link_check(cp); +} + +static int cas_txmac_interrupt(struct net_device *dev, + struct cas *cp, u32 status) +{ + u32 txmac_stat = readl(cp->regs + REG_MAC_TX_STATUS); + + if (!txmac_stat) + return 0; + + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: txmac interrupt, txmac_stat: 0x%x\n", + cp->dev->name, txmac_stat); + + /* Defer timer expiration is quite normal, + * don't even log the event. + */ + if ((txmac_stat & MAC_TX_DEFER_TIMER) && + !(txmac_stat & ~MAC_TX_DEFER_TIMER)) + return 0; + + spin_lock(&cp->stat_lock[0]); + if (txmac_stat & MAC_TX_UNDERRUN) { + printk(KERN_ERR "%s: TX MAC xmit underrun.\n", + dev->name); + cp->net_stats[0].tx_fifo_errors++; + } + + if (txmac_stat & MAC_TX_MAX_PACKET_ERR) { + printk(KERN_ERR "%s: TX MAC max packet size error.\n", + dev->name); + cp->net_stats[0].tx_errors++; + } + + /* The rest are all cases of one of the 16-bit TX + * counters expiring. + */ + if (txmac_stat & MAC_TX_COLL_NORMAL) + cp->net_stats[0].collisions += 0x10000; + + if (txmac_stat & MAC_TX_COLL_EXCESS) { + cp->net_stats[0].tx_aborted_errors += 0x10000; + cp->net_stats[0].collisions += 0x10000; + } + + if (txmac_stat & MAC_TX_COLL_LATE) { + cp->net_stats[0].tx_aborted_errors += 0x10000; + cp->net_stats[0].collisions += 0x10000; + } + spin_unlock(&cp->stat_lock[0]); + + /* We do not keep track of MAC_TX_COLL_FIRST and + * MAC_TX_PEAK_ATTEMPTS events. + */ + return 0; +} + +static void cas_load_firmware(struct cas *cp, cas_hp_inst_t *firmware) +{ + cas_hp_inst_t *inst; + u32 val; + int i; + + i = 0; + while ((inst = firmware) && inst->note) { + writel(i, cp->regs + REG_HP_INSTR_RAM_ADDR); + + val = CAS_BASE(HP_INSTR_RAM_HI_VAL, inst->val); + val |= CAS_BASE(HP_INSTR_RAM_HI_MASK, inst->mask); + writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_HI); + + val = CAS_BASE(HP_INSTR_RAM_MID_OUTARG, inst->outarg >> 10); + val |= CAS_BASE(HP_INSTR_RAM_MID_OUTOP, inst->outop); + val |= CAS_BASE(HP_INSTR_RAM_MID_FNEXT, inst->fnext); + val |= CAS_BASE(HP_INSTR_RAM_MID_FOFF, inst->foff); + val |= CAS_BASE(HP_INSTR_RAM_MID_SNEXT, inst->snext); + val |= CAS_BASE(HP_INSTR_RAM_MID_SOFF, inst->soff); + val |= CAS_BASE(HP_INSTR_RAM_MID_OP, inst->op); + writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_MID); + + val = CAS_BASE(HP_INSTR_RAM_LOW_OUTMASK, inst->outmask); + val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTSHIFT, inst->outshift); + val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTEN, inst->outenab); + val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTARG, inst->outarg); + writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_LOW); + ++firmware; + ++i; + } +} + +static void cas_init_rx_dma(struct cas *cp) +{ + u64 desc_dma = cp->block_dvma; + u32 val; + int i, size; + + /* rx free descriptors */ + val = CAS_BASE(RX_CFG_SWIVEL, RX_SWIVEL_OFF_VAL); + val |= CAS_BASE(RX_CFG_DESC_RING, RX_DESC_RINGN_INDEX(0)); + val |= CAS_BASE(RX_CFG_COMP_RING, RX_COMP_RINGN_INDEX(0)); + if ((N_RX_DESC_RINGS > 1) && + (cp->cas_flags & CAS_FLAG_REG_PLUS)) /* do desc 2 */ + val |= CAS_BASE(RX_CFG_DESC_RING1, RX_DESC_RINGN_INDEX(1)); + writel(val, cp->regs + REG_RX_CFG); + + val = (unsigned long) cp->init_rxds[0] - + (unsigned long) cp->init_block; + writel((desc_dma + val) >> 32, cp->regs + REG_RX_DB_HI); + writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_DB_LOW); + writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK); + + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + /* rx desc 2 is for IPSEC packets. however, + * we don't it that for that purpose. + */ + val = (unsigned long) cp->init_rxds[1] - + (unsigned long) cp->init_block; + writel((desc_dma + val) >> 32, cp->regs + REG_PLUS_RX_DB1_HI); + writel((desc_dma + val) & 0xffffffff, cp->regs + + REG_PLUS_RX_DB1_LOW); + writel(RX_DESC_RINGN_SIZE(1) - 4, cp->regs + + REG_PLUS_RX_KICK1); + } + + /* rx completion registers */ + val = (unsigned long) cp->init_rxcs[0] - + (unsigned long) cp->init_block; + writel((desc_dma + val) >> 32, cp->regs + REG_RX_CB_HI); + writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_CB_LOW); + + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + /* rx comp 2-4 */ + for (i = 1; i < MAX_RX_COMP_RINGS; i++) { + val = (unsigned long) cp->init_rxcs[i] - + (unsigned long) cp->init_block; + writel((desc_dma + val) >> 32, cp->regs + + REG_PLUS_RX_CBN_HI(i)); + writel((desc_dma + val) & 0xffffffff, cp->regs + + REG_PLUS_RX_CBN_LOW(i)); + } + } + + /* read selective clear regs to prevent spurious interrupts + * on reset because complete == kick. + * selective clear set up to prevent interrupts on resets + */ + readl(cp->regs + REG_INTR_STATUS_ALIAS); + writel(INTR_RX_DONE | INTR_RX_BUF_UNAVAIL, cp->regs + REG_ALIAS_CLEAR); + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + for (i = 1; i < N_RX_COMP_RINGS; i++) + readl(cp->regs + REG_PLUS_INTRN_STATUS_ALIAS(i)); + + /* 2 is different from 3 and 4 */ + if (N_RX_COMP_RINGS > 1) + writel(INTR_RX_DONE_ALT | INTR_RX_BUF_UNAVAIL_1, + cp->regs + REG_PLUS_ALIASN_CLEAR(1)); + + for (i = 2; i < N_RX_COMP_RINGS; i++) + writel(INTR_RX_DONE_ALT, + cp->regs + REG_PLUS_ALIASN_CLEAR(i)); + } + + /* set up pause thresholds */ + val = CAS_BASE(RX_PAUSE_THRESH_OFF, + cp->rx_pause_off / RX_PAUSE_THRESH_QUANTUM); + val |= CAS_BASE(RX_PAUSE_THRESH_ON, + cp->rx_pause_on / RX_PAUSE_THRESH_QUANTUM); + writel(val, cp->regs + REG_RX_PAUSE_THRESH); + + /* zero out dma reassembly buffers */ + for (i = 0; i < 64; i++) { + writel(i, cp->regs + REG_RX_TABLE_ADDR); + writel(0x0, cp->regs + REG_RX_TABLE_DATA_LOW); + writel(0x0, cp->regs + REG_RX_TABLE_DATA_MID); + writel(0x0, cp->regs + REG_RX_TABLE_DATA_HI); + } + + /* make sure address register is 0 for normal operation */ + writel(0x0, cp->regs + REG_RX_CTRL_FIFO_ADDR); + writel(0x0, cp->regs + REG_RX_IPP_FIFO_ADDR); + + /* interrupt mitigation */ +#ifdef USE_RX_BLANK + val = CAS_BASE(RX_BLANK_INTR_TIME, RX_BLANK_INTR_TIME_VAL); + val |= CAS_BASE(RX_BLANK_INTR_PKT, RX_BLANK_INTR_PKT_VAL); + writel(val, cp->regs + REG_RX_BLANK); +#else + writel(0x0, cp->regs + REG_RX_BLANK); +#endif + + /* interrupt generation as a function of low water marks for + * free desc and completion entries. these are used to trigger + * housekeeping for rx descs. we don't use the free interrupt + * as it's not very useful + */ + /* val = CAS_BASE(RX_AE_THRESH_FREE, RX_AE_FREEN_VAL(0)); */ + val = CAS_BASE(RX_AE_THRESH_COMP, RX_AE_COMP_VAL); + writel(val, cp->regs + REG_RX_AE_THRESH); + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + val = CAS_BASE(RX_AE1_THRESH_FREE, RX_AE_FREEN_VAL(1)); + writel(val, cp->regs + REG_PLUS_RX_AE1_THRESH); + } + + /* Random early detect registers. useful for congestion avoidance. + * this should be tunable. + */ + writel(0x0, cp->regs + REG_RX_RED); + + /* receive page sizes. default == 2K (0x800) */ + val = 0; + if (cp->page_size == 0x1000) + val = 0x1; + else if (cp->page_size == 0x2000) + val = 0x2; + else if (cp->page_size == 0x4000) + val = 0x3; + + /* round mtu + offset. constrain to page size. */ + size = cp->dev->mtu + 64; + if (size > cp->page_size) + size = cp->page_size; + + if (size <= 0x400) + i = 0x0; + else if (size <= 0x800) + i = 0x1; + else if (size <= 0x1000) + i = 0x2; + else + i = 0x3; + + cp->mtu_stride = 1 << (i + 10); + val = CAS_BASE(RX_PAGE_SIZE, val); + val |= CAS_BASE(RX_PAGE_SIZE_MTU_STRIDE, i); + val |= CAS_BASE(RX_PAGE_SIZE_MTU_COUNT, cp->page_size >> (i + 10)); + val |= CAS_BASE(RX_PAGE_SIZE_MTU_OFF, 0x1); + writel(val, cp->regs + REG_RX_PAGE_SIZE); + + /* enable the header parser if desired */ + if (CAS_HP_FIRMWARE == cas_prog_null) + return; + + val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS); + val |= HP_CFG_PARSE_EN | HP_CFG_SYN_INC_MASK; + val |= CAS_BASE(HP_CFG_TCP_THRESH, HP_TCP_THRESH_VAL); + writel(val, cp->regs + REG_HP_CFG); +} + +static inline void cas_rxc_init(struct cas_rx_comp *rxc) +{ + memset(rxc, 0, sizeof(*rxc)); + rxc->word4 = cpu_to_le64(RX_COMP4_ZERO); +} + +/* NOTE: we use the ENC RX DESC ring for spares. the rx_page[0,1] + * flipping is protected by the fact that the chip will not + * hand back the same page index while it's being processed. + */ +static inline cas_page_t *cas_page_spare(struct cas *cp, const int index) +{ + cas_page_t *page = cp->rx_pages[1][index]; + cas_page_t *new; + + if (page_count(page->buffer) == 1) + return page; + + new = cas_page_dequeue(cp); + if (new) { + spin_lock(&cp->rx_inuse_lock); + list_add(&page->list, &cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); + } + return new; +} + +/* this needs to be changed if we actually use the ENC RX DESC ring */ +static cas_page_t *cas_page_swap(struct cas *cp, const int ring, + const int index) +{ + cas_page_t **page0 = cp->rx_pages[0]; + cas_page_t **page1 = cp->rx_pages[1]; + + /* swap if buffer is in use */ + if (page_count(page0[index]->buffer) > 1) { + cas_page_t *new = cas_page_spare(cp, index); + if (new) { + page1[index] = page0[index]; + page0[index] = new; + } + } + RX_USED_SET(page0[index], 0); + return page0[index]; +} + +static void cas_clean_rxds(struct cas *cp) +{ + /* only clean ring 0 as ring 1 is used for spare buffers */ + struct cas_rx_desc *rxd = cp->init_rxds[0]; + int i, size; + + /* release all rx flows */ + for (i = 0; i < N_RX_FLOWS; i++) { + struct sk_buff *skb; + while ((skb = __skb_dequeue(&cp->rx_flows[i]))) { + cas_skb_release(skb); + } + } + + /* initialize descriptors */ + size = RX_DESC_RINGN_SIZE(0); + for (i = 0; i < size; i++) { + cas_page_t *page = cas_page_swap(cp, 0, i); + rxd[i].buffer = cpu_to_le64(page->dma_addr); + rxd[i].index = cpu_to_le64(CAS_BASE(RX_INDEX_NUM, i) | + CAS_BASE(RX_INDEX_RING, 0)); + } + + cp->rx_old[0] = RX_DESC_RINGN_SIZE(0) - 4; + cp->rx_last[0] = 0; + cp->cas_flags &= ~CAS_FLAG_RXD_POST(0); +} + +static void cas_clean_rxcs(struct cas *cp) +{ + int i, j; + + /* take ownership of rx comp descriptors */ + memset(cp->rx_cur, 0, sizeof(*cp->rx_cur)*N_RX_COMP_RINGS); + memset(cp->rx_new, 0, sizeof(*cp->rx_new)*N_RX_COMP_RINGS); + for (i = 0; i < N_RX_COMP_RINGS; i++) { + struct cas_rx_comp *rxc = cp->init_rxcs[i]; + for (j = 0; j < RX_COMP_RINGN_SIZE(i); j++) { + cas_rxc_init(rxc + j); + } + } +} + +#if 0 +/* When we get a RX fifo overflow, the RX unit is probably hung + * so we do the following. + * + * If any part of the reset goes wrong, we return 1 and that causes the + * whole chip to be reset. + */ +static int cas_rxmac_reset(struct cas *cp) +{ + struct net_device *dev = cp->dev; + int limit; + u32 val; + + /* First, reset MAC RX. */ + writel(cp->mac_rx_cfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG); + for (limit = 0; limit < STOP_TRIES; limit++) { + if (!(readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN)) + break; + udelay(10); + } + if (limit == STOP_TRIES) { + printk(KERN_ERR "%s: RX MAC will not disable, resetting whole " + "chip.\n", dev->name); + return 1; + } + + /* Second, disable RX DMA. */ + writel(0, cp->regs + REG_RX_CFG); + for (limit = 0; limit < STOP_TRIES; limit++) { + if (!(readl(cp->regs + REG_RX_CFG) & RX_CFG_DMA_EN)) + break; + udelay(10); + } + if (limit == STOP_TRIES) { + printk(KERN_ERR "%s: RX DMA will not disable, resetting whole " + "chip.\n", dev->name); + return 1; + } + + mdelay(5); + + /* Execute RX reset command. */ + writel(SW_RESET_RX, cp->regs + REG_SW_RESET); + for (limit = 0; limit < STOP_TRIES; limit++) { + if (!(readl(cp->regs + REG_SW_RESET) & SW_RESET_RX)) + break; + udelay(10); + } + if (limit == STOP_TRIES) { + printk(KERN_ERR "%s: RX reset command will not execute, " + "resetting whole chip.\n", dev->name); + return 1; + } + + /* reset driver rx state */ + cas_clean_rxds(cp); + cas_clean_rxcs(cp); + + /* Now, reprogram the rest of RX unit. */ + cas_init_rx_dma(cp); + + /* re-enable */ + val = readl(cp->regs + REG_RX_CFG); + writel(val | RX_CFG_DMA_EN, cp->regs + REG_RX_CFG); + writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK); + val = readl(cp->regs + REG_MAC_RX_CFG); + writel(val | MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG); + return 0; +} +#endif + +static int cas_rxmac_interrupt(struct net_device *dev, struct cas *cp, + u32 status) +{ + u32 stat = readl(cp->regs + REG_MAC_RX_STATUS); + + if (!stat) + return 0; + + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: rxmac interrupt, stat: 0x%x\n", + cp->dev->name, stat); + + /* these are all rollovers */ + spin_lock(&cp->stat_lock[0]); + if (stat & MAC_RX_ALIGN_ERR) + cp->net_stats[0].rx_frame_errors += 0x10000; + + if (stat & MAC_RX_CRC_ERR) + cp->net_stats[0].rx_crc_errors += 0x10000; + + if (stat & MAC_RX_LEN_ERR) + cp->net_stats[0].rx_length_errors += 0x10000; + + if (stat & MAC_RX_OVERFLOW) { + cp->net_stats[0].rx_over_errors++; + cp->net_stats[0].rx_fifo_errors++; + } + + /* We do not track MAC_RX_FRAME_COUNT and MAC_RX_VIOL_ERR + * events. + */ + spin_unlock(&cp->stat_lock[0]); + return 0; +} + +static int cas_mac_interrupt(struct net_device *dev, struct cas *cp, + u32 status) +{ + u32 stat = readl(cp->regs + REG_MAC_CTRL_STATUS); + + if (!stat) + return 0; + + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: mac interrupt, stat: 0x%x\n", + cp->dev->name, stat); + + /* This interrupt is just for pause frame and pause + * tracking. It is useful for diagnostics and debug + * but probably by default we will mask these events. + */ + if (stat & MAC_CTRL_PAUSE_STATE) + cp->pause_entered++; + + if (stat & MAC_CTRL_PAUSE_RECEIVED) + cp->pause_last_time_recvd = (stat >> 16); + + return 0; +} + + +/* Must be invoked under cp->lock. */ +static inline int cas_mdio_link_not_up(struct cas *cp) +{ + u16 val; + + switch (cp->lstate) { + case link_force_ret: + if (netif_msg_link(cp)) + printk(KERN_INFO "%s: Autoneg failed again, keeping" + " forced mode\n", cp->dev->name); + cas_phy_write(cp, MII_BMCR, cp->link_fcntl); + cp->timer_ticks = 5; + cp->lstate = link_force_ok; + cp->link_transition = LINK_TRANSITION_LINK_CONFIG; + break; + + case link_aneg: + val = cas_phy_read(cp, MII_BMCR); + + /* Try forced modes. we try things in the following order: + * 1000 full -> 100 full/half -> 10 half + */ + val &= ~(BMCR_ANRESTART | BMCR_ANENABLE); + val |= BMCR_FULLDPLX; + val |= (cp->cas_flags & CAS_FLAG_1000MB_CAP) ? + CAS_BMCR_SPEED1000 : BMCR_SPEED100; + cas_phy_write(cp, MII_BMCR, val); + cp->timer_ticks = 5; + cp->lstate = link_force_try; + cp->link_transition = LINK_TRANSITION_LINK_CONFIG; + break; + + case link_force_try: + /* Downgrade from 1000 to 100 to 10 Mbps if necessary. */ + val = cas_phy_read(cp, MII_BMCR); + cp->timer_ticks = 5; + if (val & CAS_BMCR_SPEED1000) { /* gigabit */ + val &= ~CAS_BMCR_SPEED1000; + val |= (BMCR_SPEED100 | BMCR_FULLDPLX); + cas_phy_write(cp, MII_BMCR, val); + break; + } + + if (val & BMCR_SPEED100) { + if (val & BMCR_FULLDPLX) /* fd failed */ + val &= ~BMCR_FULLDPLX; + else { /* 100Mbps failed */ + val &= ~BMCR_SPEED100; + } + cas_phy_write(cp, MII_BMCR, val); + break; + } + default: + break; + } + return 0; +} + + +/* must be invoked with cp->lock held */ +static int cas_mii_link_check(struct cas *cp, const u16 bmsr) +{ + int restart; + + if (bmsr & BMSR_LSTATUS) { + /* Ok, here we got a link. If we had it due to a forced + * fallback, and we were configured for autoneg, we + * retry a short autoneg pass. If you know your hub is + * broken, use ethtool ;) + */ + if ((cp->lstate == link_force_try) && + (cp->link_cntl & BMCR_ANENABLE)) { + cp->lstate = link_force_ret; + cp->link_transition = LINK_TRANSITION_LINK_CONFIG; + cas_mif_poll(cp, 0); + cp->link_fcntl = cas_phy_read(cp, MII_BMCR); + cp->timer_ticks = 5; + if (cp->opened && netif_msg_link(cp)) + printk(KERN_INFO "%s: Got link after fallback, retrying" + " autoneg once...\n", cp->dev->name); + cas_phy_write(cp, MII_BMCR, + cp->link_fcntl | BMCR_ANENABLE | + BMCR_ANRESTART); + cas_mif_poll(cp, 1); + + } else if (cp->lstate != link_up) { + cp->lstate = link_up; + cp->link_transition = LINK_TRANSITION_LINK_UP; + + if (cp->opened) { + cas_set_link_modes(cp); + netif_carrier_on(cp->dev); + } + } + return 0; + } + + /* link not up. if the link was previously up, we restart the + * whole process + */ + restart = 0; + if (cp->lstate == link_up) { + cp->lstate = link_down; + cp->link_transition = LINK_TRANSITION_LINK_DOWN; + + netif_carrier_off(cp->dev); + if (cp->opened && netif_msg_link(cp)) + printk(KERN_INFO "%s: Link down\n", + cp->dev->name); + restart = 1; + + } else if (++cp->timer_ticks > 10) + cas_mdio_link_not_up(cp); + + return restart; +} + +static int cas_mif_interrupt(struct net_device *dev, struct cas *cp, + u32 status) +{ + u32 stat = readl(cp->regs + REG_MIF_STATUS); + u16 bmsr; + + /* check for a link change */ + if (CAS_VAL(MIF_STATUS_POLL_STATUS, stat) == 0) + return 0; + + bmsr = CAS_VAL(MIF_STATUS_POLL_DATA, stat); + return cas_mii_link_check(cp, bmsr); +} + +static int cas_pci_interrupt(struct net_device *dev, struct cas *cp, + u32 status) +{ + u32 stat = readl(cp->regs + REG_PCI_ERR_STATUS); + + if (!stat) + return 0; + + printk(KERN_ERR "%s: PCI error [%04x:%04x] ", dev->name, stat, + readl(cp->regs + REG_BIM_DIAG)); + + /* cassini+ has this reserved */ + if ((stat & PCI_ERR_BADACK) && + ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0)) + printk(" "); + + if (stat & PCI_ERR_DTRTO) + printk(" "); + if (stat & PCI_ERR_OTHER) + printk(" "); + if (stat & PCI_ERR_BIM_DMA_WRITE) + printk(" "); + if (stat & PCI_ERR_BIM_DMA_READ) + printk(" "); + printk("\n"); + + if (stat & PCI_ERR_OTHER) { + u16 cfg; + + /* Interrogate PCI config space for the + * true cause. + */ + pci_read_config_word(cp->pdev, PCI_STATUS, &cfg); + printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n", + dev->name, cfg); + if (cfg & PCI_STATUS_PARITY) + printk(KERN_ERR "%s: PCI parity error detected.\n", + dev->name); + if (cfg & PCI_STATUS_SIG_TARGET_ABORT) + printk(KERN_ERR "%s: PCI target abort.\n", + dev->name); + if (cfg & PCI_STATUS_REC_TARGET_ABORT) + printk(KERN_ERR "%s: PCI master acks target abort.\n", + dev->name); + if (cfg & PCI_STATUS_REC_MASTER_ABORT) + printk(KERN_ERR "%s: PCI master abort.\n", dev->name); + if (cfg & PCI_STATUS_SIG_SYSTEM_ERROR) + printk(KERN_ERR "%s: PCI system error SERR#.\n", + dev->name); + if (cfg & PCI_STATUS_DETECTED_PARITY) + printk(KERN_ERR "%s: PCI parity error.\n", + dev->name); + + /* Write the error bits back to clear them. */ + cfg &= (PCI_STATUS_PARITY | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | + PCI_STATUS_REC_MASTER_ABORT | + PCI_STATUS_SIG_SYSTEM_ERROR | + PCI_STATUS_DETECTED_PARITY); + pci_write_config_word(cp->pdev, PCI_STATUS, cfg); + } + + /* For all PCI errors, we should reset the chip. */ + return 1; +} + +/* All non-normal interrupt conditions get serviced here. + * Returns non-zero if we should just exit the interrupt + * handler right now (ie. if we reset the card which invalidates + * all of the other original irq status bits). + */ +static int cas_abnormal_irq(struct net_device *dev, struct cas *cp, + u32 status) +{ + if (status & INTR_RX_TAG_ERROR) { + /* corrupt RX tag framing */ + if (netif_msg_rx_err(cp)) + printk(KERN_DEBUG "%s: corrupt rx tag framing\n", + cp->dev->name); + spin_lock(&cp->stat_lock[0]); + cp->net_stats[0].rx_errors++; + spin_unlock(&cp->stat_lock[0]); + goto do_reset; + } + + if (status & INTR_RX_LEN_MISMATCH) { + /* length mismatch. */ + if (netif_msg_rx_err(cp)) + printk(KERN_DEBUG "%s: length mismatch for rx frame\n", + cp->dev->name); + spin_lock(&cp->stat_lock[0]); + cp->net_stats[0].rx_errors++; + spin_unlock(&cp->stat_lock[0]); + goto do_reset; + } + + if (status & INTR_PCS_STATUS) { + if (cas_pcs_interrupt(dev, cp, status)) + goto do_reset; + } + + if (status & INTR_TX_MAC_STATUS) { + if (cas_txmac_interrupt(dev, cp, status)) + goto do_reset; + } + + if (status & INTR_RX_MAC_STATUS) { + if (cas_rxmac_interrupt(dev, cp, status)) + goto do_reset; + } + + if (status & INTR_MAC_CTRL_STATUS) { + if (cas_mac_interrupt(dev, cp, status)) + goto do_reset; + } + + if (status & INTR_MIF_STATUS) { + if (cas_mif_interrupt(dev, cp, status)) + goto do_reset; + } + + if (status & INTR_PCI_ERROR_STATUS) { + if (cas_pci_interrupt(dev, cp, status)) + goto do_reset; + } + return 0; + +do_reset: +#if 1 + atomic_inc(&cp->reset_task_pending); + atomic_inc(&cp->reset_task_pending_all); + printk(KERN_ERR "%s:reset called in cas_abnormal_irq [0x%x]\n", + dev->name, status); + schedule_work(&cp->reset_task); +#else + atomic_set(&cp->reset_task_pending, CAS_RESET_ALL); + printk(KERN_ERR "reset called in cas_abnormal_irq\n"); + schedule_work(&cp->reset_task); +#endif + return 1; +} + +/* NOTE: CAS_TABORT returns 1 or 2 so that it can be used when + * determining whether to do a netif_stop/wakeup + */ +#define CAS_TABORT(x) (((x)->cas_flags & CAS_FLAG_TARGET_ABORT) ? 2 : 1) +#define CAS_ROUND_PAGE(x) (((x) + PAGE_SIZE - 1) & PAGE_MASK) +static inline int cas_calc_tabort(struct cas *cp, const unsigned long addr, + const int len) +{ + unsigned long off = addr + len; + + if (CAS_TABORT(cp) == 1) + return 0; + if ((CAS_ROUND_PAGE(off) - off) > TX_TARGET_ABORT_LEN) + return 0; + return TX_TARGET_ABORT_LEN; +} + +static inline void cas_tx_ringN(struct cas *cp, int ring, int limit) +{ + struct cas_tx_desc *txds; + struct sk_buff **skbs; + struct net_device *dev = cp->dev; + int entry, count; + + spin_lock(&cp->tx_lock[ring]); + txds = cp->init_txds[ring]; + skbs = cp->tx_skbs[ring]; + entry = cp->tx_old[ring]; + + count = TX_BUFF_COUNT(ring, entry, limit); + while (entry != limit) { + struct sk_buff *skb = skbs[entry]; + dma_addr_t daddr; + u32 dlen; + int frag; + + if (!skb) { + /* this should never occur */ + entry = TX_DESC_NEXT(ring, entry); + continue; + } + + /* however, we might get only a partial skb release. */ + count -= skb_shinfo(skb)->nr_frags + + + cp->tx_tiny_use[ring][entry].nbufs + 1; + if (count < 0) + break; + + if (netif_msg_tx_done(cp)) + printk(KERN_DEBUG "%s: tx[%d] done, slot %d\n", + cp->dev->name, ring, entry); + + skbs[entry] = NULL; + cp->tx_tiny_use[ring][entry].nbufs = 0; + + for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { + struct cas_tx_desc *txd = txds + entry; + + daddr = le64_to_cpu(txd->buffer); + dlen = CAS_VAL(TX_DESC_BUFLEN, + le64_to_cpu(txd->control)); + pci_unmap_page(cp->pdev, daddr, dlen, + PCI_DMA_TODEVICE); + entry = TX_DESC_NEXT(ring, entry); + + /* tiny buffer may follow */ + if (cp->tx_tiny_use[ring][entry].used) { + cp->tx_tiny_use[ring][entry].used = 0; + entry = TX_DESC_NEXT(ring, entry); + } + } + + spin_lock(&cp->stat_lock[ring]); + cp->net_stats[ring].tx_packets++; + cp->net_stats[ring].tx_bytes += skb->len; + spin_unlock(&cp->stat_lock[ring]); + dev_kfree_skb_irq(skb); + } + cp->tx_old[ring] = entry; + + /* this is wrong for multiple tx rings. the net device needs + * multiple queues for this to do the right thing. we wait + * for 2*packets to be available when using tiny buffers + */ + if (netif_queue_stopped(dev) && + (TX_BUFFS_AVAIL(cp, ring) > CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1))) + netif_wake_queue(dev); + spin_unlock(&cp->tx_lock[ring]); +} + +static void cas_tx(struct net_device *dev, struct cas *cp, + u32 status) +{ + int limit, ring; +#ifdef USE_TX_COMPWB + u64 compwb = le64_to_cpu(cp->init_block->tx_compwb); +#endif + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n", + cp->dev->name, status, compwb); + /* process all the rings */ + for (ring = 0; ring < N_TX_RINGS; ring++) { +#ifdef USE_TX_COMPWB + /* use the completion writeback registers */ + limit = (CAS_VAL(TX_COMPWB_MSB, compwb) << 8) | + CAS_VAL(TX_COMPWB_LSB, compwb); + compwb = TX_COMPWB_NEXT(compwb); +#else + limit = readl(cp->regs + REG_TX_COMPN(ring)); +#endif + if (cp->tx_old[ring] != limit) + cas_tx_ringN(cp, ring, limit); + } +} + + +static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, + int entry, const u64 *words, + struct sk_buff **skbref) +{ + int dlen, hlen, len, i, alloclen; + int off, swivel = RX_SWIVEL_OFF_VAL; + struct cas_page *page; + struct sk_buff *skb; + void *addr, *crcaddr; + char *p; + + hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]); + dlen = CAS_VAL(RX_COMP1_DATA_SIZE, words[0]); + len = hlen + dlen; + + if (RX_COPY_ALWAYS || (words[2] & RX_COMP3_SMALL_PKT)) + alloclen = len; + else + alloclen = max(hlen, RX_COPY_MIN); + + skb = dev_alloc_skb(alloclen + swivel + cp->crc_size); + if (skb == NULL) + return -1; + + *skbref = skb; + skb->dev = cp->dev; + skb_reserve(skb, swivel); + + p = skb->data; + addr = crcaddr = NULL; + if (hlen) { /* always copy header pages */ + i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]); + page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)]; + off = CAS_VAL(RX_COMP2_HDR_OFF, words[1]) * 0x100 + + swivel; + + i = hlen; + if (!dlen) /* attach FCS */ + i += cp->crc_size; + pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + addr = cas_page_map(page->buffer); + memcpy(p, addr + off, i); + pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + cas_page_unmap(addr); + RX_USED_ADD(page, 0x100); + p += hlen; + swivel = 0; + } + + + if (alloclen < (hlen + dlen)) { + skb_frag_t *frag = skb_shinfo(skb)->frags; + + /* normal or jumbo packets. we use frags */ + i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]); + page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)]; + off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel; + + hlen = min(cp->page_size - off, dlen); + if (hlen < 0) { + if (netif_msg_rx_err(cp)) { + printk(KERN_DEBUG "%s: rx page overflow: " + "%d\n", cp->dev->name, hlen); + } + dev_kfree_skb_irq(skb); + return -1; + } + i = hlen; + if (i == dlen) /* attach FCS */ + i += cp->crc_size; + pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + + /* make sure we always copy a header */ + swivel = 0; + if (p == (char *) skb->data) { /* not split */ + addr = cas_page_map(page->buffer); + memcpy(p, addr + off, RX_COPY_MIN); + pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + cas_page_unmap(addr); + off += RX_COPY_MIN; + swivel = RX_COPY_MIN; + RX_USED_ADD(page, cp->mtu_stride); + } else { + RX_USED_ADD(page, hlen); + } + skb_put(skb, alloclen); + + skb_shinfo(skb)->nr_frags++; + skb->data_len += hlen - swivel; + skb->len += hlen - swivel; + + get_page(page->buffer); + frag->page = page->buffer; + frag->page_offset = off; + frag->size = hlen - swivel; + + /* any more data? */ + if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) { + hlen = dlen; + off = 0; + + i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]); + page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)]; + pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr, + hlen + cp->crc_size, + PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_device(cp->pdev, page->dma_addr, + hlen + cp->crc_size, + PCI_DMA_FROMDEVICE); + + skb_shinfo(skb)->nr_frags++; + skb->data_len += hlen; + skb->len += hlen; + frag++; + + get_page(page->buffer); + frag->page = page->buffer; + frag->page_offset = 0; + frag->size = hlen; + RX_USED_ADD(page, hlen + cp->crc_size); + } + + if (cp->crc_size) { + addr = cas_page_map(page->buffer); + crcaddr = addr + off + hlen; + } + + } else { + /* copying packet */ + if (!dlen) + goto end_copy_pkt; + + i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]); + page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)]; + off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel; + hlen = min(cp->page_size - off, dlen); + if (hlen < 0) { + if (netif_msg_rx_err(cp)) { + printk(KERN_DEBUG "%s: rx page overflow: " + "%d\n", cp->dev->name, hlen); + } + dev_kfree_skb_irq(skb); + return -1; + } + i = hlen; + if (i == dlen) /* attach FCS */ + i += cp->crc_size; + pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + addr = cas_page_map(page->buffer); + memcpy(p, addr + off, i); + pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i, + PCI_DMA_FROMDEVICE); + cas_page_unmap(addr); + if (p == (char *) skb->data) /* not split */ + RX_USED_ADD(page, cp->mtu_stride); + else + RX_USED_ADD(page, i); + + /* any more data? */ + if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) { + p += hlen; + i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]); + page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)]; + pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr, + dlen + cp->crc_size, + PCI_DMA_FROMDEVICE); + addr = cas_page_map(page->buffer); + memcpy(p, addr, dlen + cp->crc_size); + pci_dma_sync_single_for_device(cp->pdev, page->dma_addr, + dlen + cp->crc_size, + PCI_DMA_FROMDEVICE); + cas_page_unmap(addr); + RX_USED_ADD(page, dlen + cp->crc_size); + } +end_copy_pkt: + if (cp->crc_size) { + addr = NULL; + crcaddr = skb->data + alloclen; + } + skb_put(skb, alloclen); + } + + i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]); + if (cp->crc_size) { + /* checksum includes FCS. strip it out. */ + i = csum_fold(csum_partial(crcaddr, cp->crc_size, i)); + if (addr) + cas_page_unmap(addr); + } + skb->csum = ntohs(i ^ 0xffff); + skb->ip_summed = CHECKSUM_HW; + skb->protocol = eth_type_trans(skb, cp->dev); + return len; +} + + +/* we can handle up to 64 rx flows at a time. we do the same thing + * as nonreassm except that we batch up the buffers. + * NOTE: we currently just treat each flow as a bunch of packets that + * we pass up. a better way would be to coalesce the packets + * into a jumbo packet. to do that, we need to do the following: + * 1) the first packet will have a clean split between header and + * data. save both. + * 2) each time the next flow packet comes in, extend the + * data length and merge the checksums. + * 3) on flow release, fix up the header. + * 4) make sure the higher layer doesn't care. + * because packets get coalesced, we shouldn't run into fragment count + * issues. + */ +static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words, + struct sk_buff *skb) +{ + int flowid = CAS_VAL(RX_COMP3_FLOWID, words[2]) & (N_RX_FLOWS - 1); + struct sk_buff_head *flow = &cp->rx_flows[flowid]; + + /* this is protected at a higher layer, so no need to + * do any additional locking here. stick the buffer + * at the end. + */ + __skb_insert(skb, flow->prev, (struct sk_buff *) flow, flow); + if (words[0] & RX_COMP1_RELEASE_FLOW) { + while ((skb = __skb_dequeue(flow))) { + cas_skb_release(skb); + } + } +} + +/* put rx descriptor back on ring. if a buffer is in use by a higher + * layer, this will need to put in a replacement. + */ +static void cas_post_page(struct cas *cp, const int ring, const int index) +{ + cas_page_t *new; + int entry; + + entry = cp->rx_old[ring]; + + new = cas_page_swap(cp, ring, index); + cp->init_rxds[ring][entry].buffer = cpu_to_le64(new->dma_addr); + cp->init_rxds[ring][entry].index = + cpu_to_le64(CAS_BASE(RX_INDEX_NUM, index) | + CAS_BASE(RX_INDEX_RING, ring)); + + entry = RX_DESC_ENTRY(ring, entry + 1); + cp->rx_old[ring] = entry; + + if (entry % 4) + return; + + if (ring == 0) + writel(entry, cp->regs + REG_RX_KICK); + else if ((N_RX_DESC_RINGS > 1) && + (cp->cas_flags & CAS_FLAG_REG_PLUS)) + writel(entry, cp->regs + REG_PLUS_RX_KICK1); +} + + +/* only when things are bad */ +static int cas_post_rxds_ringN(struct cas *cp, int ring, int num) +{ + unsigned int entry, last, count, released; + int cluster; + cas_page_t **page = cp->rx_pages[ring]; + + entry = cp->rx_old[ring]; + + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: rxd[%d] interrupt, done: %d\n", + cp->dev->name, ring, entry); + + cluster = -1; + count = entry & 0x3; + last = RX_DESC_ENTRY(ring, num ? entry + num - 4: entry - 4); + released = 0; + while (entry != last) { + /* make a new buffer if it's still in use */ + if (page_count(page[entry]->buffer) > 1) { + cas_page_t *new = cas_page_dequeue(cp); + if (!new) { + /* let the timer know that we need to + * do this again + */ + cp->cas_flags |= CAS_FLAG_RXD_POST(ring); + if (!timer_pending(&cp->link_timer)) + mod_timer(&cp->link_timer, jiffies + + CAS_LINK_FAST_TIMEOUT); + cp->rx_old[ring] = entry; + cp->rx_last[ring] = num ? num - released : 0; + return -ENOMEM; + } + spin_lock(&cp->rx_inuse_lock); + list_add(&page[entry]->list, &cp->rx_inuse_list); + spin_unlock(&cp->rx_inuse_lock); + cp->init_rxds[ring][entry].buffer = + cpu_to_le64(new->dma_addr); + page[entry] = new; + + } + + if (++count == 4) { + cluster = entry; + count = 0; + } + released++; + entry = RX_DESC_ENTRY(ring, entry + 1); + } + cp->rx_old[ring] = entry; + + if (cluster < 0) + return 0; + + if (ring == 0) + writel(cluster, cp->regs + REG_RX_KICK); + else if ((N_RX_DESC_RINGS > 1) && + (cp->cas_flags & CAS_FLAG_REG_PLUS)) + writel(cluster, cp->regs + REG_PLUS_RX_KICK1); + return 0; +} + + +/* process a completion ring. packets are set up in three basic ways: + * small packets: should be copied header + data in single buffer. + * large packets: header and data in a single buffer. + * split packets: header in a separate buffer from data. + * data may be in multiple pages. data may be > 256 + * bytes but in a single page. + * + * NOTE: RX page posting is done in this routine as well. while there's + * the capability of using multiple RX completion rings, it isn't + * really worthwhile due to the fact that the page posting will + * force serialization on the single descriptor ring. + */ +static int cas_rx_ringN(struct cas *cp, int ring, int budget) +{ + struct cas_rx_comp *rxcs = cp->init_rxcs[ring]; + int entry, drops; + int npackets = 0; + + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: rx[%d] interrupt, done: %d/%d\n", + cp->dev->name, ring, + readl(cp->regs + REG_RX_COMP_HEAD), + cp->rx_new[ring]); + + entry = cp->rx_new[ring]; + drops = 0; + while (1) { + struct cas_rx_comp *rxc = rxcs + entry; + struct sk_buff *skb; + int type, len; + u64 words[4]; + int i, dring; + + words[0] = le64_to_cpu(rxc->word1); + words[1] = le64_to_cpu(rxc->word2); + words[2] = le64_to_cpu(rxc->word3); + words[3] = le64_to_cpu(rxc->word4); + + /* don't touch if still owned by hw */ + type = CAS_VAL(RX_COMP1_TYPE, words[0]); + if (type == 0) + break; + + /* hw hasn't cleared the zero bit yet */ + if (words[3] & RX_COMP4_ZERO) { + break; + } + + /* get info on the packet */ + if (words[3] & (RX_COMP4_LEN_MISMATCH | RX_COMP4_BAD)) { + spin_lock(&cp->stat_lock[ring]); + cp->net_stats[ring].rx_errors++; + if (words[3] & RX_COMP4_LEN_MISMATCH) + cp->net_stats[ring].rx_length_errors++; + if (words[3] & RX_COMP4_BAD) + cp->net_stats[ring].rx_crc_errors++; + spin_unlock(&cp->stat_lock[ring]); + + /* We'll just return it to Cassini. */ + drop_it: + spin_lock(&cp->stat_lock[ring]); + ++cp->net_stats[ring].rx_dropped; + spin_unlock(&cp->stat_lock[ring]); + goto next; + } + + len = cas_rx_process_pkt(cp, rxc, entry, words, &skb); + if (len < 0) { + ++drops; + goto drop_it; + } + + /* see if it's a flow re-assembly or not. the driver + * itself handles release back up. + */ + if (RX_DONT_BATCH || (type == 0x2)) { + /* non-reassm: these always get released */ + cas_skb_release(skb); + } else { + cas_rx_flow_pkt(cp, words, skb); + } + + spin_lock(&cp->stat_lock[ring]); + cp->net_stats[ring].rx_packets++; + cp->net_stats[ring].rx_bytes += len; + spin_unlock(&cp->stat_lock[ring]); + cp->dev->last_rx = jiffies; + + next: + npackets++; + + /* should it be released? */ + if (words[0] & RX_COMP1_RELEASE_HDR) { + i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]); + dring = CAS_VAL(RX_INDEX_RING, i); + i = CAS_VAL(RX_INDEX_NUM, i); + cas_post_page(cp, dring, i); + } + + if (words[0] & RX_COMP1_RELEASE_DATA) { + i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]); + dring = CAS_VAL(RX_INDEX_RING, i); + i = CAS_VAL(RX_INDEX_NUM, i); + cas_post_page(cp, dring, i); + } + + if (words[0] & RX_COMP1_RELEASE_NEXT) { + i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]); + dring = CAS_VAL(RX_INDEX_RING, i); + i = CAS_VAL(RX_INDEX_NUM, i); + cas_post_page(cp, dring, i); + } + + /* skip to the next entry */ + entry = RX_COMP_ENTRY(ring, entry + 1 + + CAS_VAL(RX_COMP1_SKIP, words[0])); +#ifdef USE_NAPI + if (budget && (npackets >= budget)) + break; +#endif + } + cp->rx_new[ring] = entry; + + if (drops) + printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", + cp->dev->name); + return npackets; +} + + +/* put completion entries back on the ring */ +static void cas_post_rxcs_ringN(struct net_device *dev, + struct cas *cp, int ring) +{ + struct cas_rx_comp *rxc = cp->init_rxcs[ring]; + int last, entry; + + last = cp->rx_cur[ring]; + entry = cp->rx_new[ring]; + if (netif_msg_intr(cp)) + printk(KERN_DEBUG "%s: rxc[%d] interrupt, done: %d/%d\n", + dev->name, ring, readl(cp->regs + REG_RX_COMP_HEAD), + entry); + + /* zero and re-mark descriptors */ + while (last != entry) { + cas_rxc_init(rxc + last); + last = RX_COMP_ENTRY(ring, last + 1); + } + cp->rx_cur[ring] = last; + + if (ring == 0) + writel(last, cp->regs + REG_RX_COMP_TAIL); + else if (cp->cas_flags & CAS_FLAG_REG_PLUS) + writel(last, cp->regs + REG_PLUS_RX_COMPN_TAIL(ring)); +} + + + +/* cassini can use all four PCI interrupts for the completion ring. + * rings 3 and 4 are identical + */ +#if defined(USE_PCI_INTC) || defined(USE_PCI_INTD) +static inline void cas_handle_irqN(struct net_device *dev, + struct cas *cp, const u32 status, + const int ring) +{ + if (status & (INTR_RX_COMP_FULL_ALT | INTR_RX_COMP_AF_ALT)) + cas_post_rxcs_ringN(dev, cp, ring); +} + +static irqreturn_t cas_interruptN(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct cas *cp = netdev_priv(dev); + unsigned long flags; + int ring; + u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring)); + + /* check for shared irq */ + if (status == 0) + return IRQ_NONE; + + ring = (irq == cp->pci_irq_INTC) ? 2 : 3; + spin_lock_irqsave(&cp->lock, flags); + if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ +#ifdef USE_NAPI + cas_mask_intr(cp); + netif_rx_schedule(dev); +#else + cas_rx_ringN(cp, ring, 0); +#endif + status &= ~INTR_RX_DONE_ALT; + } + + if (status) + cas_handle_irqN(dev, cp, status, ring); + spin_unlock_irqrestore(&cp->lock, flags); + return IRQ_HANDLED; +} +#endif + +#ifdef USE_PCI_INTB +/* everything but rx packets */ +static inline void cas_handle_irq1(struct cas *cp, const u32 status) +{ + if (status & INTR_RX_BUF_UNAVAIL_1) { + /* Frame arrived, no free RX buffers available. + * NOTE: we can get this on a link transition. */ + cas_post_rxds_ringN(cp, 1, 0); + spin_lock(&cp->stat_lock[1]); + cp->net_stats[1].rx_dropped++; + spin_unlock(&cp->stat_lock[1]); + } + + if (status & INTR_RX_BUF_AE_1) + cas_post_rxds_ringN(cp, 1, RX_DESC_RINGN_SIZE(1) - + RX_AE_FREEN_VAL(1)); + + if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL)) + cas_post_rxcs_ringN(cp, 1); +} + +/* ring 2 handles a few more events than 3 and 4 */ +static irqreturn_t cas_interrupt1(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct cas *cp = netdev_priv(dev); + unsigned long flags; + u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1)); + + /* check for shared interrupt */ + if (status == 0) + return IRQ_NONE; + + spin_lock_irqsave(&cp->lock, flags); + if (status & INTR_RX_DONE_ALT) { /* handle rx separately */ +#ifdef USE_NAPI + cas_mask_intr(cp); + netif_rx_schedule(dev); +#else + cas_rx_ringN(cp, 1, 0); +#endif + status &= ~INTR_RX_DONE_ALT; + } + if (status) + cas_handle_irq1(cp, status); + spin_unlock_irqrestore(&cp->lock, flags); + return IRQ_HANDLED; +} +#endif + +static inline void cas_handle_irq(struct net_device *dev, + struct cas *cp, const u32 status) +{ + /* housekeeping interrupts */ + if (status & INTR_ERROR_MASK) + cas_abnormal_irq(dev, cp, status); + + if (status & INTR_RX_BUF_UNAVAIL) { + /* Frame arrived, no free RX buffers available. + * NOTE: we can get this on a link transition. + */ + cas_post_rxds_ringN(cp, 0, 0); + spin_lock(&cp->stat_lock[0]); + cp->net_stats[0].rx_dropped++; + spin_unlock(&cp->stat_lock[0]); + } else if (status & INTR_RX_BUF_AE) { + cas_post_rxds_ringN(cp, 0, RX_DESC_RINGN_SIZE(0) - + RX_AE_FREEN_VAL(0)); + } + + if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL)) + cas_post_rxcs_ringN(dev, cp, 0); +} + +static irqreturn_t cas_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct cas *cp = netdev_priv(dev); + unsigned long flags; + u32 status = readl(cp->regs + REG_INTR_STATUS); + + if (status == 0) + return IRQ_NONE; + + spin_lock_irqsave(&cp->lock, flags); + if (status & (INTR_TX_ALL | INTR_TX_INTME)) { + cas_tx(dev, cp, status); + status &= ~(INTR_TX_ALL | INTR_TX_INTME); + } + + if (status & INTR_RX_DONE) { +#ifdef USE_NAPI + cas_mask_intr(cp); + netif_rx_schedule(dev); +#else + cas_rx_ringN(cp, 0, 0); +#endif + status &= ~INTR_RX_DONE; + } + + if (status) + cas_handle_irq(dev, cp, status); + spin_unlock_irqrestore(&cp->lock, flags); + return IRQ_HANDLED; +} + + +#ifdef USE_NAPI +static int cas_poll(struct net_device *dev, int *budget) +{ + struct cas *cp = netdev_priv(dev); + int i, enable_intr, todo, credits; + u32 status = readl(cp->regs + REG_INTR_STATUS); + unsigned long flags; + + spin_lock_irqsave(&cp->lock, flags); + cas_tx(dev, cp, status); + spin_unlock_irqrestore(&cp->lock, flags); + + /* NAPI rx packets. we spread the credits across all of the + * rxc rings + */ + todo = min(*budget, dev->quota); + + /* to make sure we're fair with the work we loop through each + * ring N_RX_COMP_RING times with a request of + * todo / N_RX_COMP_RINGS + */ + enable_intr = 1; + credits = 0; + for (i = 0; i < N_RX_COMP_RINGS; i++) { + int j; + for (j = 0; j < N_RX_COMP_RINGS; j++) { + credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS); + if (credits >= todo) { + enable_intr = 0; + goto rx_comp; + } + } + } + +rx_comp: + *budget -= credits; + dev->quota -= credits; + + /* final rx completion */ + spin_lock_irqsave(&cp->lock, flags); + if (status) + cas_handle_irq(dev, cp, status); + +#ifdef USE_PCI_INTB + if (N_RX_COMP_RINGS > 1) { + status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1)); + if (status) + cas_handle_irq1(dev, cp, status); + } +#endif + +#ifdef USE_PCI_INTC + if (N_RX_COMP_RINGS > 2) { + status = readl(cp->regs + REG_PLUS_INTRN_STATUS(2)); + if (status) + cas_handle_irqN(dev, cp, status, 2); + } +#endif + +#ifdef USE_PCI_INTD + if (N_RX_COMP_RINGS > 3) { + status = readl(cp->regs + REG_PLUS_INTRN_STATUS(3)); + if (status) + cas_handle_irqN(dev, cp, status, 3); + } +#endif + spin_unlock_irqrestore(&cp->lock, flags); + if (enable_intr) { + netif_rx_complete(dev); + cas_unmask_intr(cp); + return 0; + } + return 1; +} +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void cas_netpoll(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + + cas_disable_irq(cp, 0); + cas_interrupt(cp->pdev->irq, dev, NULL); + cas_enable_irq(cp, 0); + +#ifdef USE_PCI_INTB + if (N_RX_COMP_RINGS > 1) { + /* cas_interrupt1(); */ + } +#endif +#ifdef USE_PCI_INTC + if (N_RX_COMP_RINGS > 2) { + /* cas_interruptN(); */ + } +#endif +#ifdef USE_PCI_INTD + if (N_RX_COMP_RINGS > 3) { + /* cas_interruptN(); */ + } +#endif +} +#endif + +static void cas_tx_timeout(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + + printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); + if (!cp->hw_running) { + printk("%s: hrm.. hw not running!\n", dev->name); + return; + } + + printk(KERN_ERR "%s: MIF_STATE[%08x]\n", + dev->name, readl(cp->regs + REG_MIF_STATE_MACHINE)); + + printk(KERN_ERR "%s: MAC_STATE[%08x]\n", + dev->name, readl(cp->regs + REG_MAC_STATE_MACHINE)); + + printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x] " + "FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n", + dev->name, + readl(cp->regs + REG_TX_CFG), + readl(cp->regs + REG_MAC_TX_STATUS), + readl(cp->regs + REG_MAC_TX_CFG), + readl(cp->regs + REG_TX_FIFO_PKT_CNT), + readl(cp->regs + REG_TX_FIFO_WRITE_PTR), + readl(cp->regs + REG_TX_FIFO_READ_PTR), + readl(cp->regs + REG_TX_SM_1), + readl(cp->regs + REG_TX_SM_2)); + + printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n", + dev->name, + readl(cp->regs + REG_RX_CFG), + readl(cp->regs + REG_MAC_RX_STATUS), + readl(cp->regs + REG_MAC_RX_CFG)); + + printk(KERN_ERR "%s: HP_STATE[%08x:%08x:%08x:%08x]\n", + dev->name, + readl(cp->regs + REG_HP_STATE_MACHINE), + readl(cp->regs + REG_HP_STATUS0), + readl(cp->regs + REG_HP_STATUS1), + readl(cp->regs + REG_HP_STATUS2)); + +#if 1 + atomic_inc(&cp->reset_task_pending); + atomic_inc(&cp->reset_task_pending_all); + schedule_work(&cp->reset_task); +#else + atomic_set(&cp->reset_task_pending, CAS_RESET_ALL); + schedule_work(&cp->reset_task); +#endif +} + +static inline int cas_intme(int ring, int entry) +{ + /* Algorithm: IRQ every 1/2 of descriptors. */ + if (!(entry & ((TX_DESC_RINGN_SIZE(ring) >> 1) - 1))) + return 1; + return 0; +} + + +static void cas_write_txd(struct cas *cp, int ring, int entry, + dma_addr_t mapping, int len, u64 ctrl, int last) +{ + struct cas_tx_desc *txd = cp->init_txds[ring] + entry; + + ctrl |= CAS_BASE(TX_DESC_BUFLEN, len); + if (cas_intme(ring, entry)) + ctrl |= TX_DESC_INTME; + if (last) + ctrl |= TX_DESC_EOF; + txd->control = cpu_to_le64(ctrl); + txd->buffer = cpu_to_le64(mapping); +} + +static inline void *tx_tiny_buf(struct cas *cp, const int ring, + const int entry) +{ + return cp->tx_tiny_bufs[ring] + TX_TINY_BUF_LEN*entry; +} + +static inline dma_addr_t tx_tiny_map(struct cas *cp, const int ring, + const int entry, const int tentry) +{ + cp->tx_tiny_use[ring][tentry].nbufs++; + cp->tx_tiny_use[ring][entry].used = 1; + return cp->tx_tiny_dvma[ring] + TX_TINY_BUF_LEN*entry; +} + +static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, + struct sk_buff *skb) +{ + struct net_device *dev = cp->dev; + int entry, nr_frags, frag, tabort, tentry; + dma_addr_t mapping; + unsigned long flags; + u64 ctrl; + u32 len; + + spin_lock_irqsave(&cp->tx_lock[ring], flags); + + /* This is a hard error, log it. */ + if (TX_BUFFS_AVAIL(cp, ring) <= + CAS_TABORT(cp)*(skb_shinfo(skb)->nr_frags + 1)) { + netif_stop_queue(dev); + spin_unlock_irqrestore(&cp->tx_lock[ring], flags); + printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " + "queue awake!\n", dev->name); + return 1; + } + + ctrl = 0; + if (skb->ip_summed == CHECKSUM_HW) { + u64 csum_start_off, csum_stuff_off; + + csum_start_off = (u64) (skb->h.raw - skb->data); + csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + + ctrl = TX_DESC_CSUM_EN | + CAS_BASE(TX_DESC_CSUM_START, csum_start_off) | + CAS_BASE(TX_DESC_CSUM_STUFF, csum_stuff_off); + } + + entry = cp->tx_new[ring]; + cp->tx_skbs[ring][entry] = skb; + + nr_frags = skb_shinfo(skb)->nr_frags; + len = skb_headlen(skb); + mapping = pci_map_page(cp->pdev, virt_to_page(skb->data), + offset_in_page(skb->data), len, + PCI_DMA_TODEVICE); + + tentry = entry; + tabort = cas_calc_tabort(cp, (unsigned long) skb->data, len); + if (unlikely(tabort)) { + /* NOTE: len is always > tabort */ + cas_write_txd(cp, ring, entry, mapping, len - tabort, + ctrl | TX_DESC_SOF, 0); + entry = TX_DESC_NEXT(ring, entry); + + memcpy(tx_tiny_buf(cp, ring, entry), skb->data + + len - tabort, tabort); + mapping = tx_tiny_map(cp, ring, entry, tentry); + cas_write_txd(cp, ring, entry, mapping, tabort, ctrl, + (nr_frags == 0)); + } else { + cas_write_txd(cp, ring, entry, mapping, len, ctrl | + TX_DESC_SOF, (nr_frags == 0)); + } + entry = TX_DESC_NEXT(ring, entry); + + for (frag = 0; frag < nr_frags; frag++) { + skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag]; + + len = fragp->size; + mapping = pci_map_page(cp->pdev, fragp->page, + fragp->page_offset, len, + PCI_DMA_TODEVICE); + + tabort = cas_calc_tabort(cp, fragp->page_offset, len); + if (unlikely(tabort)) { + void *addr; + + /* NOTE: len is always > tabort */ + cas_write_txd(cp, ring, entry, mapping, len - tabort, + ctrl, 0); + entry = TX_DESC_NEXT(ring, entry); + + addr = cas_page_map(fragp->page); + memcpy(tx_tiny_buf(cp, ring, entry), + addr + fragp->page_offset + len - tabort, + tabort); + cas_page_unmap(addr); + mapping = tx_tiny_map(cp, ring, entry, tentry); + len = tabort; + } + + cas_write_txd(cp, ring, entry, mapping, len, ctrl, + (frag + 1 == nr_frags)); + entry = TX_DESC_NEXT(ring, entry); + } + + cp->tx_new[ring] = entry; + if (TX_BUFFS_AVAIL(cp, ring) <= CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1)) + netif_stop_queue(dev); + + if (netif_msg_tx_queued(cp)) + printk(KERN_DEBUG "%s: tx[%d] queued, slot %d, skblen %d, " + "avail %d\n", + dev->name, ring, entry, skb->len, + TX_BUFFS_AVAIL(cp, ring)); + writel(entry, cp->regs + REG_TX_KICKN(ring)); + spin_unlock_irqrestore(&cp->tx_lock[ring], flags); + return 0; +} + +static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + + /* this is only used as a load-balancing hint, so it doesn't + * need to be SMP safe + */ + static int ring; + + skb = skb_padto(skb, cp->min_frame_size); + if (!skb) + return 0; + + /* XXX: we need some higher-level QoS hooks to steer packets to + * individual queues. + */ + if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb)) + return 1; + dev->trans_start = jiffies; + return 0; +} + +static void cas_init_tx_dma(struct cas *cp) +{ + u64 desc_dma = cp->block_dvma; + unsigned long off; + u32 val; + int i; + + /* set up tx completion writeback registers. must be 8-byte aligned */ +#ifdef USE_TX_COMPWB + off = offsetof(struct cas_init_block, tx_compwb); + writel((desc_dma + off) >> 32, cp->regs + REG_TX_COMPWB_DB_HI); + writel((desc_dma + off) & 0xffffffff, cp->regs + REG_TX_COMPWB_DB_LOW); +#endif + + /* enable completion writebacks, enable paced mode, + * disable read pipe, and disable pre-interrupt compwbs + */ + val = TX_CFG_COMPWB_Q1 | TX_CFG_COMPWB_Q2 | + TX_CFG_COMPWB_Q3 | TX_CFG_COMPWB_Q4 | + TX_CFG_DMA_RDPIPE_DIS | TX_CFG_PACED_MODE | + TX_CFG_INTR_COMPWB_DIS; + + /* write out tx ring info and tx desc bases */ + for (i = 0; i < MAX_TX_RINGS; i++) { + off = (unsigned long) cp->init_txds[i] - + (unsigned long) cp->init_block; + + val |= CAS_TX_RINGN_BASE(i); + writel((desc_dma + off) >> 32, cp->regs + REG_TX_DBN_HI(i)); + writel((desc_dma + off) & 0xffffffff, cp->regs + + REG_TX_DBN_LOW(i)); + /* don't zero out the kick register here as the system + * will wedge + */ + } + writel(val, cp->regs + REG_TX_CFG); + + /* program max burst sizes. these numbers should be different + * if doing QoS. + */ +#ifdef USE_QOS + writel(0x800, cp->regs + REG_TX_MAXBURST_0); + writel(0x1600, cp->regs + REG_TX_MAXBURST_1); + writel(0x2400, cp->regs + REG_TX_MAXBURST_2); + writel(0x4800, cp->regs + REG_TX_MAXBURST_3); +#else + writel(0x800, cp->regs + REG_TX_MAXBURST_0); + writel(0x800, cp->regs + REG_TX_MAXBURST_1); + writel(0x800, cp->regs + REG_TX_MAXBURST_2); + writel(0x800, cp->regs + REG_TX_MAXBURST_3); +#endif +} + +/* Must be invoked under cp->lock. */ +static inline void cas_init_dma(struct cas *cp) +{ + cas_init_tx_dma(cp); + cas_init_rx_dma(cp); +} + +/* Must be invoked under cp->lock. */ +static u32 cas_setup_multicast(struct cas *cp) +{ + u32 rxcfg = 0; + int i; + + if (cp->dev->flags & IFF_PROMISC) { + rxcfg |= MAC_RX_CFG_PROMISC_EN; + + } else if (cp->dev->flags & IFF_ALLMULTI) { + for (i=0; i < 16; i++) + writel(0xFFFF, cp->regs + REG_MAC_HASH_TABLEN(i)); + rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; + + } else { + u16 hash_table[16]; + u32 crc; + struct dev_mc_list *dmi = cp->dev->mc_list; + int i; + + /* use the alternate mac address registers for the + * first 15 multicast addresses + */ + for (i = 1; i <= CAS_MC_EXACT_MATCH_SIZE; i++) { + if (!dmi) { + writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 0)); + writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 1)); + writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 2)); + continue; + } + writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], + cp->regs + REG_MAC_ADDRN(i*3 + 0)); + writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], + cp->regs + REG_MAC_ADDRN(i*3 + 1)); + writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], + cp->regs + REG_MAC_ADDRN(i*3 + 2)); + dmi = dmi->next; + } + + /* use hw hash table for the next series of + * multicast addresses + */ + memset(hash_table, 0, sizeof(hash_table)); + while (dmi) { + crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); + crc >>= 24; + hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); + dmi = dmi->next; + } + for (i=0; i < 16; i++) + writel(hash_table[i], cp->regs + + REG_MAC_HASH_TABLEN(i)); + rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; + } + + return rxcfg; +} + +/* must be invoked under cp->stat_lock[N_TX_RINGS] */ +static void cas_clear_mac_err(struct cas *cp) +{ + writel(0, cp->regs + REG_MAC_COLL_NORMAL); + writel(0, cp->regs + REG_MAC_COLL_FIRST); + writel(0, cp->regs + REG_MAC_COLL_EXCESS); + writel(0, cp->regs + REG_MAC_COLL_LATE); + writel(0, cp->regs + REG_MAC_TIMER_DEFER); + writel(0, cp->regs + REG_MAC_ATTEMPTS_PEAK); + writel(0, cp->regs + REG_MAC_RECV_FRAME); + writel(0, cp->regs + REG_MAC_LEN_ERR); + writel(0, cp->regs + REG_MAC_ALIGN_ERR); + writel(0, cp->regs + REG_MAC_FCS_ERR); + writel(0, cp->regs + REG_MAC_RX_CODE_ERR); +} + + +static void cas_mac_reset(struct cas *cp) +{ + int i; + + /* do both TX and RX reset */ + writel(0x1, cp->regs + REG_MAC_TX_RESET); + writel(0x1, cp->regs + REG_MAC_RX_RESET); + + /* wait for TX */ + i = STOP_TRIES; + while (i-- > 0) { + if (readl(cp->regs + REG_MAC_TX_RESET) == 0) + break; + udelay(10); + } + + /* wait for RX */ + i = STOP_TRIES; + while (i-- > 0) { + if (readl(cp->regs + REG_MAC_RX_RESET) == 0) + break; + udelay(10); + } + + if (readl(cp->regs + REG_MAC_TX_RESET) | + readl(cp->regs + REG_MAC_RX_RESET)) + printk(KERN_ERR "%s: mac tx[%d]/rx[%d] reset failed [%08x]\n", + cp->dev->name, readl(cp->regs + REG_MAC_TX_RESET), + readl(cp->regs + REG_MAC_RX_RESET), + readl(cp->regs + REG_MAC_STATE_MACHINE)); +} + + +/* Must be invoked under cp->lock. */ +static void cas_init_mac(struct cas *cp) +{ + unsigned char *e = &cp->dev->dev_addr[0]; + int i; +#ifdef CONFIG_CASSINI_MULTICAST_REG_WRITE + u32 rxcfg; +#endif + cas_mac_reset(cp); + + /* setup core arbitration weight register */ + writel(CAWR_RR_DIS, cp->regs + REG_CAWR); + + /* XXX Use pci_dma_burst_advice() */ +#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA) + /* set the infinite burst register for chips that don't have + * pci issues. + */ + if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) == 0) + writel(INF_BURST_EN, cp->regs + REG_INF_BURST); +#endif + + writel(0x1BF0, cp->regs + REG_MAC_SEND_PAUSE); + + writel(0x00, cp->regs + REG_MAC_IPG0); + writel(0x08, cp->regs + REG_MAC_IPG1); + writel(0x04, cp->regs + REG_MAC_IPG2); + + /* change later for 802.3z */ + writel(0x40, cp->regs + REG_MAC_SLOT_TIME); + + /* min frame + FCS */ + writel(ETH_ZLEN + 4, cp->regs + REG_MAC_FRAMESIZE_MIN); + + /* Ethernet payload + header + FCS + optional VLAN tag. NOTE: we + * specify the maximum frame size to prevent RX tag errors on + * oversized frames. + */ + writel(CAS_BASE(MAC_FRAMESIZE_MAX_BURST, 0x2000) | + CAS_BASE(MAC_FRAMESIZE_MAX_FRAME, + (CAS_MAX_MTU + ETH_HLEN + 4 + 4)), + cp->regs + REG_MAC_FRAMESIZE_MAX); + + /* NOTE: crc_size is used as a surrogate for half-duplex. + * workaround saturn half-duplex issue by increasing preamble + * size to 65 bytes. + */ + if ((cp->cas_flags & CAS_FLAG_SATURN) && cp->crc_size) + writel(0x41, cp->regs + REG_MAC_PA_SIZE); + else + writel(0x07, cp->regs + REG_MAC_PA_SIZE); + writel(0x04, cp->regs + REG_MAC_JAM_SIZE); + writel(0x10, cp->regs + REG_MAC_ATTEMPT_LIMIT); + writel(0x8808, cp->regs + REG_MAC_CTRL_TYPE); + + writel((e[5] | (e[4] << 8)) & 0x3ff, cp->regs + REG_MAC_RANDOM_SEED); + + writel(0, cp->regs + REG_MAC_ADDR_FILTER0); + writel(0, cp->regs + REG_MAC_ADDR_FILTER1); + writel(0, cp->regs + REG_MAC_ADDR_FILTER2); + writel(0, cp->regs + REG_MAC_ADDR_FILTER2_1_MASK); + writel(0, cp->regs + REG_MAC_ADDR_FILTER0_MASK); + + /* setup mac address in perfect filter array */ + for (i = 0; i < 45; i++) + writel(0x0, cp->regs + REG_MAC_ADDRN(i)); + + writel((e[4] << 8) | e[5], cp->regs + REG_MAC_ADDRN(0)); + writel((e[2] << 8) | e[3], cp->regs + REG_MAC_ADDRN(1)); + writel((e[0] << 8) | e[1], cp->regs + REG_MAC_ADDRN(2)); + + writel(0x0001, cp->regs + REG_MAC_ADDRN(42)); + writel(0xc200, cp->regs + REG_MAC_ADDRN(43)); + writel(0x0180, cp->regs + REG_MAC_ADDRN(44)); + +#ifndef CONFIG_CASSINI_MULTICAST_REG_WRITE + cp->mac_rx_cfg = cas_setup_multicast(cp); +#else + /* WTZ: Do what Adrian did in cas_set_multicast. Doing + * a writel does not seem to be necessary because Cassini + * seems to preserve the configuration when we do the reset. + * If the chip is in trouble, though, it is not clear if we + * can really count on this behavior. cas_set_multicast uses + * spin_lock_irqsave, but we are called only in cas_init_hw and + * cas_init_hw is protected by cas_lock_all, which calls + * spin_lock_irq (so it doesn't need to save the flags, and + * we should be OK for the writel, as that is the only + * difference). + */ + cp->mac_rx_cfg = rxcfg = cas_setup_multicast(cp); + writel(rxcfg, cp->regs + REG_MAC_RX_CFG); +#endif + spin_lock(&cp->stat_lock[N_TX_RINGS]); + cas_clear_mac_err(cp); + spin_unlock(&cp->stat_lock[N_TX_RINGS]); + + /* Setup MAC interrupts. We want to get all of the interesting + * counter expiration events, but we do not want to hear about + * normal rx/tx as the DMA engine tells us that. + */ + writel(MAC_TX_FRAME_XMIT, cp->regs + REG_MAC_TX_MASK); + writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK); + + /* Don't enable even the PAUSE interrupts for now, we + * make no use of those events other than to record them. + */ + writel(0xffffffff, cp->regs + REG_MAC_CTRL_MASK); +} + +/* Must be invoked under cp->lock. */ +static void cas_init_pause_thresholds(struct cas *cp) +{ + /* Calculate pause thresholds. Setting the OFF threshold to the + * full RX fifo size effectively disables PAUSE generation + */ + if (cp->rx_fifo_size <= (2 * 1024)) { + cp->rx_pause_off = cp->rx_pause_on = cp->rx_fifo_size; + } else { + int max_frame = (cp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63; + if (max_frame * 3 > cp->rx_fifo_size) { + cp->rx_pause_off = 7104; + cp->rx_pause_on = 960; + } else { + int off = (cp->rx_fifo_size - (max_frame * 2)); + int on = off - max_frame; + cp->rx_pause_off = off; + cp->rx_pause_on = on; + } + } +} + +static int cas_vpd_match(const void __iomem *p, const char *str) +{ + int len = strlen(str) + 1; + int i; + + for (i = 0; i < len; i++) { + if (readb(p + i) != str[i]) + return 0; + } + return 1; +} + + +/* get the mac address by reading the vpd information in the rom. + * also get the phy type and determine if there's an entropy generator. + * NOTE: this is a bit convoluted for the following reasons: + * 1) vpd info has order-dependent mac addresses for multinic cards + * 2) the only way to determine the nic order is to use the slot + * number. + * 3) fiber cards don't have bridges, so their slot numbers don't + * mean anything. + * 4) we don't actually know we have a fiber card until after + * the mac addresses are parsed. + */ +static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, + const int offset) +{ + void __iomem *p = cp->regs + REG_EXPANSION_ROM_RUN_START; + void __iomem *base, *kstart; + int i, len; + int found = 0; +#define VPD_FOUND_MAC 0x01 +#define VPD_FOUND_PHY 0x02 + + int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */ + int mac_off = 0; + + /* give us access to the PROM */ + writel(BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_PAD, + cp->regs + REG_BIM_LOCAL_DEV_EN); + + /* check for an expansion rom */ + if (readb(p) != 0x55 || readb(p + 1) != 0xaa) + goto use_random_mac_addr; + + /* search for beginning of vpd */ + base = 0; + for (i = 2; i < EXPANSION_ROM_SIZE; i++) { + /* check for PCIR */ + if ((readb(p + i + 0) == 0x50) && + (readb(p + i + 1) == 0x43) && + (readb(p + i + 2) == 0x49) && + (readb(p + i + 3) == 0x52)) { + base = p + (readb(p + i + 8) | + (readb(p + i + 9) << 8)); + break; + } + } + + if (!base || (readb(base) != 0x82)) + goto use_random_mac_addr; + + i = (readb(base + 1) | (readb(base + 2) << 8)) + 3; + while (i < EXPANSION_ROM_SIZE) { + if (readb(base + i) != 0x90) /* no vpd found */ + goto use_random_mac_addr; + + /* found a vpd field */ + len = readb(base + i + 1) | (readb(base + i + 2) << 8); + + /* extract keywords */ + kstart = base + i + 3; + p = kstart; + while ((p - kstart) < len) { + int klen = readb(p + 2); + int j; + char type; + + p += 3; + + /* look for the following things: + * -- correct length == 29 + * 3 (type) + 2 (size) + + * 18 (strlen("local-mac-address") + 1) + + * 6 (mac addr) + * -- VPD Instance 'I' + * -- VPD Type Bytes 'B' + * -- VPD data length == 6 + * -- property string == local-mac-address + * + * -- correct length == 24 + * 3 (type) + 2 (size) + + * 12 (strlen("entropy-dev") + 1) + + * 7 (strlen("vms110") + 1) + * -- VPD Instance 'I' + * -- VPD Type String 'B' + * -- VPD data length == 7 + * -- property string == entropy-dev + * + * -- correct length == 18 + * 3 (type) + 2 (size) + + * 9 (strlen("phy-type") + 1) + + * 4 (strlen("pcs") + 1) + * -- VPD Instance 'I' + * -- VPD Type String 'S' + * -- VPD data length == 4 + * -- property string == phy-type + * + * -- correct length == 23 + * 3 (type) + 2 (size) + + * 14 (strlen("phy-interface") + 1) + + * 4 (strlen("pcs") + 1) + * -- VPD Instance 'I' + * -- VPD Type String 'S' + * -- VPD data length == 4 + * -- property string == phy-interface + */ + if (readb(p) != 'I') + goto next; + + /* finally, check string and length */ + type = readb(p + 3); + if (type == 'B') { + if ((klen == 29) && readb(p + 4) == 6 && + cas_vpd_match(p + 5, + "local-mac-address")) { + if (mac_off++ > offset) + goto next; + + /* set mac address */ + for (j = 0; j < 6; j++) + dev_addr[j] = + readb(p + 23 + j); + goto found_mac; + } + } + + if (type != 'S') + goto next; + +#ifdef USE_ENTROPY_DEV + if ((klen == 24) && + cas_vpd_match(p + 5, "entropy-dev") && + cas_vpd_match(p + 17, "vms110")) { + cp->cas_flags |= CAS_FLAG_ENTROPY_DEV; + goto next; + } +#endif + + if (found & VPD_FOUND_PHY) + goto next; + + if ((klen == 18) && readb(p + 4) == 4 && + cas_vpd_match(p + 5, "phy-type")) { + if (cas_vpd_match(p + 14, "pcs")) { + phy_type = CAS_PHY_SERDES; + goto found_phy; + } + } + + if ((klen == 23) && readb(p + 4) == 4 && + cas_vpd_match(p + 5, "phy-interface")) { + if (cas_vpd_match(p + 19, "pcs")) { + phy_type = CAS_PHY_SERDES; + goto found_phy; + } + } +found_mac: + found |= VPD_FOUND_MAC; + goto next; + +found_phy: + found |= VPD_FOUND_PHY; + +next: + p += klen; + } + i += len + 3; + } + +use_random_mac_addr: + if (found & VPD_FOUND_MAC) + goto done; + + /* Sun MAC prefix then 3 random bytes. */ + printk(PFX "MAC address not found in ROM VPD\n"); + dev_addr[0] = 0x08; + dev_addr[1] = 0x00; + dev_addr[2] = 0x20; + get_random_bytes(dev_addr + 3, 3); + +done: + writel(0, cp->regs + REG_BIM_LOCAL_DEV_EN); + return phy_type; +} + +/* check pci invariants */ +static void cas_check_pci_invariants(struct cas *cp) +{ + struct pci_dev *pdev = cp->pdev; + u8 rev; + + cp->cas_flags = 0; + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + if ((pdev->vendor == PCI_VENDOR_ID_SUN) && + (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) { + if (rev >= CAS_ID_REVPLUS) + cp->cas_flags |= CAS_FLAG_REG_PLUS; + if (rev < CAS_ID_REVPLUS02u) + cp->cas_flags |= CAS_FLAG_TARGET_ABORT; + + /* Original Cassini supports HW CSUM, but it's not + * enabled by default as it can trigger TX hangs. + */ + if (rev < CAS_ID_REV2) + cp->cas_flags |= CAS_FLAG_NO_HW_CSUM; + } else { + /* Only sun has original cassini chips. */ + cp->cas_flags |= CAS_FLAG_REG_PLUS; + + /* We use a flag because the same phy might be externally + * connected. + */ + if ((pdev->vendor == PCI_VENDOR_ID_NS) && + (pdev->device == PCI_DEVICE_ID_NS_SATURN)) + cp->cas_flags |= CAS_FLAG_SATURN; + } +} + + +static int cas_check_invariants(struct cas *cp) +{ + struct pci_dev *pdev = cp->pdev; + u32 cfg; + int i; + + /* get page size for rx buffers. */ + cp->page_order = 0; +#ifdef USE_PAGE_ORDER + if (PAGE_SHIFT < CAS_JUMBO_PAGE_SHIFT) { + /* see if we can allocate larger pages */ + struct page *page = alloc_pages(GFP_ATOMIC, + CAS_JUMBO_PAGE_SHIFT - + PAGE_SHIFT); + if (page) { + __free_pages(page, CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT); + cp->page_order = CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT; + } else { + printk(PFX "MTU limited to %d bytes\n", CAS_MAX_MTU); + } + } +#endif + cp->page_size = (PAGE_SIZE << cp->page_order); + + /* Fetch the FIFO configurations. */ + cp->tx_fifo_size = readl(cp->regs + REG_TX_FIFO_SIZE) * 64; + cp->rx_fifo_size = RX_FIFO_SIZE; + + /* finish phy determination. MDIO1 takes precedence over MDIO0 if + * they're both connected. + */ + cp->phy_type = cas_get_vpd_info(cp, cp->dev->dev_addr, + PCI_SLOT(pdev->devfn)); + if (cp->phy_type & CAS_PHY_SERDES) { + cp->cas_flags |= CAS_FLAG_1000MB_CAP; + return 0; /* no more checking needed */ + } + + /* MII */ + cfg = readl(cp->regs + REG_MIF_CFG); + if (cfg & MIF_CFG_MDIO_1) { + cp->phy_type = CAS_PHY_MII_MDIO1; + } else if (cfg & MIF_CFG_MDIO_0) { + cp->phy_type = CAS_PHY_MII_MDIO0; + } + + cas_mif_poll(cp, 0); + writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE); + + for (i = 0; i < 32; i++) { + u32 phy_id; + int j; + + for (j = 0; j < 3; j++) { + cp->phy_addr = i; + phy_id = cas_phy_read(cp, MII_PHYSID1) << 16; + phy_id |= cas_phy_read(cp, MII_PHYSID2); + if (phy_id && (phy_id != 0xFFFFFFFF)) { + cp->phy_id = phy_id; + goto done; + } + } + } + printk(KERN_ERR PFX "MII phy did not respond [%08x]\n", + readl(cp->regs + REG_MIF_STATE_MACHINE)); + return -1; + +done: + /* see if we can do gigabit */ + cfg = cas_phy_read(cp, MII_BMSR); + if ((cfg & CAS_BMSR_1000_EXTEND) && + cas_phy_read(cp, CAS_MII_1000_EXTEND)) + cp->cas_flags |= CAS_FLAG_1000MB_CAP; + return 0; +} + +/* Must be invoked under cp->lock. */ +static inline void cas_start_dma(struct cas *cp) +{ + int i; + u32 val; + int txfailed = 0; + + /* enable dma */ + val = readl(cp->regs + REG_TX_CFG) | TX_CFG_DMA_EN; + writel(val, cp->regs + REG_TX_CFG); + val = readl(cp->regs + REG_RX_CFG) | RX_CFG_DMA_EN; + writel(val, cp->regs + REG_RX_CFG); + + /* enable the mac */ + val = readl(cp->regs + REG_MAC_TX_CFG) | MAC_TX_CFG_EN; + writel(val, cp->regs + REG_MAC_TX_CFG); + val = readl(cp->regs + REG_MAC_RX_CFG) | MAC_RX_CFG_EN; + writel(val, cp->regs + REG_MAC_RX_CFG); + + i = STOP_TRIES; + while (i-- > 0) { + val = readl(cp->regs + REG_MAC_TX_CFG); + if ((val & MAC_TX_CFG_EN)) + break; + udelay(10); + } + if (i < 0) txfailed = 1; + i = STOP_TRIES; + while (i-- > 0) { + val = readl(cp->regs + REG_MAC_RX_CFG); + if ((val & MAC_RX_CFG_EN)) { + if (txfailed) { + printk(KERN_ERR + "%s: enabling mac failed [tx:%08x:%08x].\n", + cp->dev->name, + readl(cp->regs + REG_MIF_STATE_MACHINE), + readl(cp->regs + REG_MAC_STATE_MACHINE)); + } + goto enable_rx_done; + } + udelay(10); + } + printk(KERN_ERR "%s: enabling mac failed [%s:%08x:%08x].\n", + cp->dev->name, + (txfailed? "tx,rx":"rx"), + readl(cp->regs + REG_MIF_STATE_MACHINE), + readl(cp->regs + REG_MAC_STATE_MACHINE)); + +enable_rx_done: + cas_unmask_intr(cp); /* enable interrupts */ + writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK); + writel(0, cp->regs + REG_RX_COMP_TAIL); + + if (cp->cas_flags & CAS_FLAG_REG_PLUS) { + if (N_RX_DESC_RINGS > 1) + writel(RX_DESC_RINGN_SIZE(1) - 4, + cp->regs + REG_PLUS_RX_KICK1); + + for (i = 1; i < N_RX_COMP_RINGS; i++) + writel(0, cp->regs + REG_PLUS_RX_COMPN_TAIL(i)); + } +} + +/* Must be invoked under cp->lock. */ +static void cas_read_pcs_link_mode(struct cas *cp, int *fd, int *spd, + int *pause) +{ + u32 val = readl(cp->regs + REG_PCS_MII_LPA); + *fd = (val & PCS_MII_LPA_FD) ? 1 : 0; + *pause = (val & PCS_MII_LPA_SYM_PAUSE) ? 0x01 : 0x00; + if (val & PCS_MII_LPA_ASYM_PAUSE) + *pause |= 0x10; + *spd = 1000; +} + +/* Must be invoked under cp->lock. */ +static void cas_read_mii_link_mode(struct cas *cp, int *fd, int *spd, + int *pause) +{ + u32 val; + + *fd = 0; + *spd = 10; + *pause = 0; + + /* use GMII registers */ + val = cas_phy_read(cp, MII_LPA); + if (val & CAS_LPA_PAUSE) + *pause = 0x01; + + if (val & CAS_LPA_ASYM_PAUSE) + *pause |= 0x10; + + if (val & LPA_DUPLEX) + *fd = 1; + if (val & LPA_100) + *spd = 100; + + if (cp->cas_flags & CAS_FLAG_1000MB_CAP) { + val = cas_phy_read(cp, CAS_MII_1000_STATUS); + if (val & (CAS_LPA_1000FULL | CAS_LPA_1000HALF)) + *spd = 1000; + if (val & CAS_LPA_1000FULL) + *fd = 1; + } +} + +/* A link-up condition has occurred, initialize and enable the + * rest of the chip. + * + * Must be invoked under cp->lock. + */ +static void cas_set_link_modes(struct cas *cp) +{ + u32 val; + int full_duplex, speed, pause; + + full_duplex = 0; + speed = 10; + pause = 0; + + if (CAS_PHY_MII(cp->phy_type)) { + cas_mif_poll(cp, 0); + val = cas_phy_read(cp, MII_BMCR); + if (val & BMCR_ANENABLE) { + cas_read_mii_link_mode(cp, &full_duplex, &speed, + &pause); + } else { + if (val & BMCR_FULLDPLX) + full_duplex = 1; + + if (val & BMCR_SPEED100) + speed = 100; + else if (val & CAS_BMCR_SPEED1000) + speed = (cp->cas_flags & CAS_FLAG_1000MB_CAP) ? + 1000 : 100; + } + cas_mif_poll(cp, 1); + + } else { + val = readl(cp->regs + REG_PCS_MII_CTRL); + cas_read_pcs_link_mode(cp, &full_duplex, &speed, &pause); + if ((val & PCS_MII_AUTONEG_EN) == 0) { + if (val & PCS_MII_CTRL_DUPLEX) + full_duplex = 1; + } + } + + if (netif_msg_link(cp)) + printk(KERN_INFO "%s: Link up at %d Mbps, %s-duplex.\n", + cp->dev->name, speed, (full_duplex ? "full" : "half")); + + val = MAC_XIF_TX_MII_OUTPUT_EN | MAC_XIF_LINK_LED; + if (CAS_PHY_MII(cp->phy_type)) { + val |= MAC_XIF_MII_BUFFER_OUTPUT_EN; + if (!full_duplex) + val |= MAC_XIF_DISABLE_ECHO; + } + if (full_duplex) + val |= MAC_XIF_FDPLX_LED; + if (speed == 1000) + val |= MAC_XIF_GMII_MODE; + writel(val, cp->regs + REG_MAC_XIF_CFG); + + /* deal with carrier and collision detect. */ + val = MAC_TX_CFG_IPG_EN; + if (full_duplex) { + val |= MAC_TX_CFG_IGNORE_CARRIER; + val |= MAC_TX_CFG_IGNORE_COLL; + } else { +#ifndef USE_CSMA_CD_PROTO + val |= MAC_TX_CFG_NEVER_GIVE_UP_EN; + val |= MAC_TX_CFG_NEVER_GIVE_UP_LIM; +#endif + } + /* val now set up for REG_MAC_TX_CFG */ + + /* If gigabit and half-duplex, enable carrier extension + * mode. increase slot time to 512 bytes as well. + * else, disable it and make sure slot time is 64 bytes. + * also activate checksum bug workaround + */ + if ((speed == 1000) && !full_duplex) { + writel(val | MAC_TX_CFG_CARRIER_EXTEND, + cp->regs + REG_MAC_TX_CFG); + + val = readl(cp->regs + REG_MAC_RX_CFG); + val &= ~MAC_RX_CFG_STRIP_FCS; /* checksum workaround */ + writel(val | MAC_RX_CFG_CARRIER_EXTEND, + cp->regs + REG_MAC_RX_CFG); + + writel(0x200, cp->regs + REG_MAC_SLOT_TIME); + + cp->crc_size = 4; + /* minimum size gigabit frame at half duplex */ + cp->min_frame_size = CAS_1000MB_MIN_FRAME; + + } else { + writel(val, cp->regs + REG_MAC_TX_CFG); + + /* checksum bug workaround. don't strip FCS when in + * half-duplex mode + */ + val = readl(cp->regs + REG_MAC_RX_CFG); + if (full_duplex) { + val |= MAC_RX_CFG_STRIP_FCS; + cp->crc_size = 0; + cp->min_frame_size = CAS_MIN_MTU; + } else { + val &= ~MAC_RX_CFG_STRIP_FCS; + cp->crc_size = 4; + cp->min_frame_size = CAS_MIN_FRAME; + } + writel(val & ~MAC_RX_CFG_CARRIER_EXTEND, + cp->regs + REG_MAC_RX_CFG); + writel(0x40, cp->regs + REG_MAC_SLOT_TIME); + } + + if (netif_msg_link(cp)) { + if (pause & 0x01) { + printk(KERN_INFO "%s: Pause is enabled " + "(rxfifo: %d off: %d on: %d)\n", + cp->dev->name, + cp->rx_fifo_size, + cp->rx_pause_off, + cp->rx_pause_on); + } else if (pause & 0x10) { + printk(KERN_INFO "%s: TX pause enabled\n", + cp->dev->name); + } else { + printk(KERN_INFO "%s: Pause is disabled\n", + cp->dev->name); + } + } + + val = readl(cp->regs + REG_MAC_CTRL_CFG); + val &= ~(MAC_CTRL_CFG_SEND_PAUSE_EN | MAC_CTRL_CFG_RECV_PAUSE_EN); + if (pause) { /* symmetric or asymmetric pause */ + val |= MAC_CTRL_CFG_SEND_PAUSE_EN; + if (pause & 0x01) { /* symmetric pause */ + val |= MAC_CTRL_CFG_RECV_PAUSE_EN; + } + } + writel(val, cp->regs + REG_MAC_CTRL_CFG); + cas_start_dma(cp); +} + +/* Must be invoked under cp->lock. */ +static void cas_init_hw(struct cas *cp, int restart_link) +{ + if (restart_link) + cas_phy_init(cp); + + cas_init_pause_thresholds(cp); + cas_init_mac(cp); + cas_init_dma(cp); + + if (restart_link) { + /* Default aneg parameters */ + cp->timer_ticks = 0; + cas_begin_auto_negotiation(cp, NULL); + } else if (cp->lstate == link_up) { + cas_set_link_modes(cp); + netif_carrier_on(cp->dev); + } +} + +/* Must be invoked under cp->lock. on earlier cassini boards, + * SOFT_0 is tied to PCI reset. we use this to force a pci reset, + * let it settle out, and then restore pci state. + */ +static void cas_hard_reset(struct cas *cp) +{ + writel(BIM_LOCAL_DEV_SOFT_0, cp->regs + REG_BIM_LOCAL_DEV_EN); + udelay(20); + pci_restore_state(cp->pdev); +} + + +static void cas_global_reset(struct cas *cp, int blkflag) +{ + int limit; + + /* issue a global reset. don't use RSTOUT. */ + if (blkflag && !CAS_PHY_MII(cp->phy_type)) { + /* For PCS, when the blkflag is set, we should set the + * SW_REST_BLOCK_PCS_SLINK bit to prevent the results of + * the last autonegotiation from being cleared. We'll + * need some special handling if the chip is set into a + * loopback mode. + */ + writel((SW_RESET_TX | SW_RESET_RX | SW_RESET_BLOCK_PCS_SLINK), + cp->regs + REG_SW_RESET); + } else { + writel(SW_RESET_TX | SW_RESET_RX, cp->regs + REG_SW_RESET); + } + + /* need to wait at least 3ms before polling register */ + mdelay(3); + + limit = STOP_TRIES; + while (limit-- > 0) { + u32 val = readl(cp->regs + REG_SW_RESET); + if ((val & (SW_RESET_TX | SW_RESET_RX)) == 0) + goto done; + udelay(10); + } + printk(KERN_ERR "%s: sw reset failed.\n", cp->dev->name); + +done: + /* enable various BIM interrupts */ + writel(BIM_CFG_DPAR_INTR_ENABLE | BIM_CFG_RMA_INTR_ENABLE | + BIM_CFG_RTA_INTR_ENABLE, cp->regs + REG_BIM_CFG); + + /* clear out pci error status mask for handled errors. + * we don't deal with DMA counter overflows as they happen + * all the time. + */ + writel(0xFFFFFFFFU & ~(PCI_ERR_BADACK | PCI_ERR_DTRTO | + PCI_ERR_OTHER | PCI_ERR_BIM_DMA_WRITE | + PCI_ERR_BIM_DMA_READ), cp->regs + + REG_PCI_ERR_STATUS_MASK); + + /* set up for MII by default to address mac rx reset timeout + * issue + */ + writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE); +} + +static void cas_reset(struct cas *cp, int blkflag) +{ + u32 val; + + cas_mask_intr(cp); + cas_global_reset(cp, blkflag); + cas_mac_reset(cp); + cas_entropy_reset(cp); + + /* disable dma engines. */ + val = readl(cp->regs + REG_TX_CFG); + val &= ~TX_CFG_DMA_EN; + writel(val, cp->regs + REG_TX_CFG); + + val = readl(cp->regs + REG_RX_CFG); + val &= ~RX_CFG_DMA_EN; + writel(val, cp->regs + REG_RX_CFG); + + /* program header parser */ + if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) || + (CAS_HP_ALT_FIRMWARE == cas_prog_null)) { + cas_load_firmware(cp, CAS_HP_FIRMWARE); + } else { + cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE); + } + + /* clear out error registers */ + spin_lock(&cp->stat_lock[N_TX_RINGS]); + cas_clear_mac_err(cp); + spin_unlock(&cp->stat_lock[N_TX_RINGS]); +} + +/* Shut down the chip, must be called with pm_sem held. */ +static void cas_shutdown(struct cas *cp) +{ + unsigned long flags; + + /* Make us not-running to avoid timers respawning */ + cp->hw_running = 0; + + del_timer_sync(&cp->link_timer); + + /* Stop the reset task */ +#if 0 + while (atomic_read(&cp->reset_task_pending_mtu) || + atomic_read(&cp->reset_task_pending_spare) || + atomic_read(&cp->reset_task_pending_all)) + schedule(); + +#else + while (atomic_read(&cp->reset_task_pending)) + schedule(); +#endif + /* Actually stop the chip */ + cas_lock_all_save(cp, flags); + cas_reset(cp, 0); + if (cp->cas_flags & CAS_FLAG_SATURN) + cas_phy_powerdown(cp); + cas_unlock_all_restore(cp, flags); +} + +static int cas_change_mtu(struct net_device *dev, int new_mtu) +{ + struct cas *cp = netdev_priv(dev); + + if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU) + return -EINVAL; + + dev->mtu = new_mtu; + if (!netif_running(dev) || !netif_device_present(dev)) + return 0; + + /* let the reset task handle it */ +#if 1 + atomic_inc(&cp->reset_task_pending); + if ((cp->phy_type & CAS_PHY_SERDES)) { + atomic_inc(&cp->reset_task_pending_all); + } else { + atomic_inc(&cp->reset_task_pending_mtu); + } + schedule_work(&cp->reset_task); +#else + atomic_set(&cp->reset_task_pending, (cp->phy_type & CAS_PHY_SERDES) ? + CAS_RESET_ALL : CAS_RESET_MTU); + printk(KERN_ERR "reset called in cas_change_mtu\n"); + schedule_work(&cp->reset_task); +#endif + + flush_scheduled_work(); + return 0; +} + +static void cas_clean_txd(struct cas *cp, int ring) +{ + struct cas_tx_desc *txd = cp->init_txds[ring]; + struct sk_buff *skb, **skbs = cp->tx_skbs[ring]; + u64 daddr, dlen; + int i, size; + + size = TX_DESC_RINGN_SIZE(ring); + for (i = 0; i < size; i++) { + int frag; + + if (skbs[i] == NULL) + continue; + + skb = skbs[i]; + skbs[i] = NULL; + + for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { + int ent = i & (size - 1); + + /* first buffer is never a tiny buffer and so + * needs to be unmapped. + */ + daddr = le64_to_cpu(txd[ent].buffer); + dlen = CAS_VAL(TX_DESC_BUFLEN, + le64_to_cpu(txd[ent].control)); + pci_unmap_page(cp->pdev, daddr, dlen, + PCI_DMA_TODEVICE); + + if (frag != skb_shinfo(skb)->nr_frags) { + i++; + + /* next buffer might by a tiny buffer. + * skip past it. + */ + ent = i & (size - 1); + if (cp->tx_tiny_use[ring][ent].used) + i++; + } + } + dev_kfree_skb_any(skb); + } + + /* zero out tiny buf usage */ + memset(cp->tx_tiny_use[ring], 0, size*sizeof(*cp->tx_tiny_use[ring])); +} + +/* freed on close */ +static inline void cas_free_rx_desc(struct cas *cp, int ring) +{ + cas_page_t **page = cp->rx_pages[ring]; + int i, size; + + size = RX_DESC_RINGN_SIZE(ring); + for (i = 0; i < size; i++) { + if (page[i]) { + cas_page_free(cp, page[i]); + page[i] = NULL; + } + } +} + +static void cas_free_rxds(struct cas *cp) +{ + int i; + + for (i = 0; i < N_RX_DESC_RINGS; i++) + cas_free_rx_desc(cp, i); +} + +/* Must be invoked under cp->lock. */ +static void cas_clean_rings(struct cas *cp) +{ + int i; + + /* need to clean all tx rings */ + memset(cp->tx_old, 0, sizeof(*cp->tx_old)*N_TX_RINGS); + memset(cp->tx_new, 0, sizeof(*cp->tx_new)*N_TX_RINGS); + for (i = 0; i < N_TX_RINGS; i++) + cas_clean_txd(cp, i); + + /* zero out init block */ + memset(cp->init_block, 0, sizeof(struct cas_init_block)); + cas_clean_rxds(cp); + cas_clean_rxcs(cp); +} + +/* allocated on open */ +static inline int cas_alloc_rx_desc(struct cas *cp, int ring) +{ + cas_page_t **page = cp->rx_pages[ring]; + int size, i = 0; + + size = RX_DESC_RINGN_SIZE(ring); + for (i = 0; i < size; i++) { + if ((page[i] = cas_page_alloc(cp, GFP_KERNEL)) == NULL) + return -1; + } + return 0; +} + +static int cas_alloc_rxds(struct cas *cp) +{ + int i; + + for (i = 0; i < N_RX_DESC_RINGS; i++) { + if (cas_alloc_rx_desc(cp, i) < 0) { + cas_free_rxds(cp); + return -1; + } + } + return 0; +} + +static void cas_reset_task(void *data) +{ + struct cas *cp = (struct cas *) data; +#if 0 + int pending = atomic_read(&cp->reset_task_pending); +#else + int pending_all = atomic_read(&cp->reset_task_pending_all); + int pending_spare = atomic_read(&cp->reset_task_pending_spare); + int pending_mtu = atomic_read(&cp->reset_task_pending_mtu); + + if (pending_all == 0 && pending_spare == 0 && pending_mtu == 0) { + /* We can have more tasks scheduled than actually + * needed. + */ + atomic_dec(&cp->reset_task_pending); + return; + } +#endif + /* The link went down, we reset the ring, but keep + * DMA stopped. Use this function for reset + * on error as well. + */ + if (cp->hw_running) { + unsigned long flags; + + /* Make sure we don't get interrupts or tx packets */ + netif_device_detach(cp->dev); + cas_lock_all_save(cp, flags); + + if (cp->opened) { + /* We call cas_spare_recover when we call cas_open. + * but we do not initialize the lists cas_spare_recover + * uses until cas_open is called. + */ + cas_spare_recover(cp, GFP_ATOMIC); + } +#if 1 + /* test => only pending_spare set */ + if (!pending_all && !pending_mtu) + goto done; +#else + if (pending == CAS_RESET_SPARE) + goto done; +#endif + /* when pending == CAS_RESET_ALL, the following + * call to cas_init_hw will restart auto negotiation. + * Setting the second argument of cas_reset to + * !(pending == CAS_RESET_ALL) will set this argument + * to 1 (avoiding reinitializing the PHY for the normal + * PCS case) when auto negotiation is not restarted. + */ +#if 1 + cas_reset(cp, !(pending_all > 0)); + if (cp->opened) + cas_clean_rings(cp); + cas_init_hw(cp, (pending_all > 0)); +#else + cas_reset(cp, !(pending == CAS_RESET_ALL)); + if (cp->opened) + cas_clean_rings(cp); + cas_init_hw(cp, pending == CAS_RESET_ALL); +#endif + +done: + cas_unlock_all_restore(cp, flags); + netif_device_attach(cp->dev); + } +#if 1 + atomic_sub(pending_all, &cp->reset_task_pending_all); + atomic_sub(pending_spare, &cp->reset_task_pending_spare); + atomic_sub(pending_mtu, &cp->reset_task_pending_mtu); + atomic_dec(&cp->reset_task_pending); +#else + atomic_set(&cp->reset_task_pending, 0); +#endif +} + +static void cas_link_timer(unsigned long data) +{ + struct cas *cp = (struct cas *) data; + int mask, pending = 0, reset = 0; + unsigned long flags; + + if (link_transition_timeout != 0 && + cp->link_transition_jiffies_valid && + ((jiffies - cp->link_transition_jiffies) > + (link_transition_timeout))) { + /* One-second counter so link-down workaround doesn't + * cause resets to occur so fast as to fool the switch + * into thinking the link is down. + */ + cp->link_transition_jiffies_valid = 0; + } + + if (!cp->hw_running) + return; + + spin_lock_irqsave(&cp->lock, flags); + cas_lock_tx(cp); + cas_entropy_gather(cp); + + /* If the link task is still pending, we just + * reschedule the link timer + */ +#if 1 + if (atomic_read(&cp->reset_task_pending_all) || + atomic_read(&cp->reset_task_pending_spare) || + atomic_read(&cp->reset_task_pending_mtu)) + goto done; +#else + if (atomic_read(&cp->reset_task_pending)) + goto done; +#endif + + /* check for rx cleaning */ + if ((mask = (cp->cas_flags & CAS_FLAG_RXD_POST_MASK))) { + int i, rmask; + + for (i = 0; i < MAX_RX_DESC_RINGS; i++) { + rmask = CAS_FLAG_RXD_POST(i); + if ((mask & rmask) == 0) + continue; + + /* post_rxds will do a mod_timer */ + if (cas_post_rxds_ringN(cp, i, cp->rx_last[i]) < 0) { + pending = 1; + continue; + } + cp->cas_flags &= ~rmask; + } + } + + if (CAS_PHY_MII(cp->phy_type)) { + u16 bmsr; + cas_mif_poll(cp, 0); + bmsr = cas_phy_read(cp, MII_BMSR); + /* WTZ: Solaris driver reads this twice, but that + * may be due to the PCS case and the use of a + * common implementation. Read it twice here to be + * safe. + */ + bmsr = cas_phy_read(cp, MII_BMSR); + cas_mif_poll(cp, 1); + readl(cp->regs + REG_MIF_STATUS); /* avoid dups */ + reset = cas_mii_link_check(cp, bmsr); + } else { + reset = cas_pcs_link_check(cp); + } + + if (reset) + goto done; + + /* check for tx state machine confusion */ + if ((readl(cp->regs + REG_MAC_TX_STATUS) & MAC_TX_FRAME_XMIT) == 0) { + u32 val = readl(cp->regs + REG_MAC_STATE_MACHINE); + u32 wptr, rptr; + int tlm = CAS_VAL(MAC_SM_TLM, val); + + if (((tlm == 0x5) || (tlm == 0x3)) && + (CAS_VAL(MAC_SM_ENCAP_SM, val) == 0)) { + if (netif_msg_tx_err(cp)) + printk(KERN_DEBUG "%s: tx err: " + "MAC_STATE[%08x]\n", + cp->dev->name, val); + reset = 1; + goto done; + } + + val = readl(cp->regs + REG_TX_FIFO_PKT_CNT); + wptr = readl(cp->regs + REG_TX_FIFO_WRITE_PTR); + rptr = readl(cp->regs + REG_TX_FIFO_READ_PTR); + if ((val == 0) && (wptr != rptr)) { + if (netif_msg_tx_err(cp)) + printk(KERN_DEBUG "%s: tx err: " + "TX_FIFO[%08x:%08x:%08x]\n", + cp->dev->name, val, wptr, rptr); + reset = 1; + } + + if (reset) + cas_hard_reset(cp); + } + +done: + if (reset) { +#if 1 + atomic_inc(&cp->reset_task_pending); + atomic_inc(&cp->reset_task_pending_all); + schedule_work(&cp->reset_task); +#else + atomic_set(&cp->reset_task_pending, CAS_RESET_ALL); + printk(KERN_ERR "reset called in cas_link_timer\n"); + schedule_work(&cp->reset_task); +#endif + } + + if (!pending) + mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT); + cas_unlock_tx(cp); + spin_unlock_irqrestore(&cp->lock, flags); +} + +/* tiny buffers are used to avoid target abort issues with + * older cassini's + */ +static void cas_tx_tiny_free(struct cas *cp) +{ + struct pci_dev *pdev = cp->pdev; + int i; + + for (i = 0; i < N_TX_RINGS; i++) { + if (!cp->tx_tiny_bufs[i]) + continue; + + pci_free_consistent(pdev, TX_TINY_BUF_BLOCK, + cp->tx_tiny_bufs[i], + cp->tx_tiny_dvma[i]); + cp->tx_tiny_bufs[i] = NULL; + } +} + +static int cas_tx_tiny_alloc(struct cas *cp) +{ + struct pci_dev *pdev = cp->pdev; + int i; + + for (i = 0; i < N_TX_RINGS; i++) { + cp->tx_tiny_bufs[i] = + pci_alloc_consistent(pdev, TX_TINY_BUF_BLOCK, + &cp->tx_tiny_dvma[i]); + if (!cp->tx_tiny_bufs[i]) { + cas_tx_tiny_free(cp); + return -1; + } + } + return 0; +} + + +static int cas_open(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + int hw_was_up, err; + unsigned long flags; + + down(&cp->pm_sem); + + hw_was_up = cp->hw_running; + + /* The power-management semaphore protects the hw_running + * etc. state so it is safe to do this bit without cp->lock + */ + if (!cp->hw_running) { + /* Reset the chip */ + cas_lock_all_save(cp, flags); + /* We set the second arg to cas_reset to zero + * because cas_init_hw below will have its second + * argument set to non-zero, which will force + * autonegotiation to start. + */ + cas_reset(cp, 0); + cp->hw_running = 1; + cas_unlock_all_restore(cp, flags); + } + + if (cas_tx_tiny_alloc(cp) < 0) + return -ENOMEM; + + /* alloc rx descriptors */ + err = -ENOMEM; + if (cas_alloc_rxds(cp) < 0) + goto err_tx_tiny; + + /* allocate spares */ + cas_spare_init(cp); + cas_spare_recover(cp, GFP_KERNEL); + + /* We can now request the interrupt as we know it's masked + * on the controller. cassini+ has up to 4 interrupts + * that can be used, but you need to do explicit pci interrupt + * mapping to expose them + */ + if (request_irq(cp->pdev->irq, cas_interrupt, + SA_SHIRQ, dev->name, (void *) dev)) { + printk(KERN_ERR "%s: failed to request irq !\n", + cp->dev->name); + err = -EAGAIN; + goto err_spare; + } + + /* init hw */ + cas_lock_all_save(cp, flags); + cas_clean_rings(cp); + cas_init_hw(cp, !hw_was_up); + cp->opened = 1; + cas_unlock_all_restore(cp, flags); + + netif_start_queue(dev); + up(&cp->pm_sem); + return 0; + +err_spare: + cas_spare_free(cp); + cas_free_rxds(cp); +err_tx_tiny: + cas_tx_tiny_free(cp); + up(&cp->pm_sem); + return err; +} + +static int cas_close(struct net_device *dev) +{ + unsigned long flags; + struct cas *cp = netdev_priv(dev); + + /* Make sure we don't get distracted by suspend/resume */ + down(&cp->pm_sem); + + netif_stop_queue(dev); + + /* Stop traffic, mark us closed */ + cas_lock_all_save(cp, flags); + cp->opened = 0; + cas_reset(cp, 0); + cas_phy_init(cp); + cas_begin_auto_negotiation(cp, NULL); + cas_clean_rings(cp); + cas_unlock_all_restore(cp, flags); + + free_irq(cp->pdev->irq, (void *) dev); + cas_spare_free(cp); + cas_free_rxds(cp); + cas_tx_tiny_free(cp); + up(&cp->pm_sem); + return 0; +} + +static struct { + const char name[ETH_GSTRING_LEN]; +} ethtool_cassini_statnames[] = { + {"collisions"}, + {"rx_bytes"}, + {"rx_crc_errors"}, + {"rx_dropped"}, + {"rx_errors"}, + {"rx_fifo_errors"}, + {"rx_frame_errors"}, + {"rx_length_errors"}, + {"rx_over_errors"}, + {"rx_packets"}, + {"tx_aborted_errors"}, + {"tx_bytes"}, + {"tx_dropped"}, + {"tx_errors"}, + {"tx_fifo_errors"}, + {"tx_packets"} +}; +#define CAS_NUM_STAT_KEYS (sizeof(ethtool_cassini_statnames)/ETH_GSTRING_LEN) + +static struct { + const int offsets; /* neg. values for 2nd arg to cas_read_phy */ +} ethtool_register_table[] = { + {-MII_BMSR}, + {-MII_BMCR}, + {REG_CAWR}, + {REG_INF_BURST}, + {REG_BIM_CFG}, + {REG_RX_CFG}, + {REG_HP_CFG}, + {REG_MAC_TX_CFG}, + {REG_MAC_RX_CFG}, + {REG_MAC_CTRL_CFG}, + {REG_MAC_XIF_CFG}, + {REG_MIF_CFG}, + {REG_PCS_CFG}, + {REG_SATURN_PCFG}, + {REG_PCS_MII_STATUS}, + {REG_PCS_STATE_MACHINE}, + {REG_MAC_COLL_EXCESS}, + {REG_MAC_COLL_LATE} +}; +#define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int)) +#define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) + +static u8 *cas_get_regs(struct cas *cp) +{ + u8 *ptr = kmalloc(CAS_MAX_REGS, GFP_KERNEL); + u8 *p; + int i; + unsigned long flags; + + if (!ptr) + return NULL; + + spin_lock_irqsave(&cp->lock, flags); + for (i = 0, p = ptr; i < CAS_REG_LEN ; i ++, p += sizeof(u32)) { + u16 hval; + u32 val; + if (ethtool_register_table[i].offsets < 0) { + hval = cas_phy_read(cp, + -ethtool_register_table[i].offsets); + val = hval; + } else { + val= readl(cp->regs+ethtool_register_table[i].offsets); + } + memcpy(p, (u8 *)&val, sizeof(u32)); + } + spin_unlock_irqrestore(&cp->lock, flags); + + return ptr; +} + +static struct net_device_stats *cas_get_stats(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + struct net_device_stats *stats = cp->net_stats; + unsigned long flags; + int i; + unsigned long tmp; + + /* we collate all of the stats into net_stats[N_TX_RING] */ + if (!cp->hw_running) + return stats + N_TX_RINGS; + + /* collect outstanding stats */ + /* WTZ: the Cassini spec gives these as 16 bit counters but + * stored in 32-bit words. Added a mask of 0xffff to be safe, + * in case the chip somehow puts any garbage in the other bits. + * Also, counter usage didn't seem to mach what Adrian did + * in the parts of the code that set these quantities. Made + * that consistent. + */ + spin_lock_irqsave(&cp->stat_lock[N_TX_RINGS], flags); + stats[N_TX_RINGS].rx_crc_errors += + readl(cp->regs + REG_MAC_FCS_ERR) & 0xffff; + stats[N_TX_RINGS].rx_frame_errors += + readl(cp->regs + REG_MAC_ALIGN_ERR) &0xffff; + stats[N_TX_RINGS].rx_length_errors += + readl(cp->regs + REG_MAC_LEN_ERR) & 0xffff; +#if 1 + tmp = (readl(cp->regs + REG_MAC_COLL_EXCESS) & 0xffff) + + (readl(cp->regs + REG_MAC_COLL_LATE) & 0xffff); + stats[N_TX_RINGS].tx_aborted_errors += tmp; + stats[N_TX_RINGS].collisions += + tmp + (readl(cp->regs + REG_MAC_COLL_NORMAL) & 0xffff); +#else + stats[N_TX_RINGS].tx_aborted_errors += + readl(cp->regs + REG_MAC_COLL_EXCESS); + stats[N_TX_RINGS].collisions += readl(cp->regs + REG_MAC_COLL_EXCESS) + + readl(cp->regs + REG_MAC_COLL_LATE); +#endif + cas_clear_mac_err(cp); + + /* saved bits that are unique to ring 0 */ + spin_lock(&cp->stat_lock[0]); + stats[N_TX_RINGS].collisions += stats[0].collisions; + stats[N_TX_RINGS].rx_over_errors += stats[0].rx_over_errors; + stats[N_TX_RINGS].rx_frame_errors += stats[0].rx_frame_errors; + stats[N_TX_RINGS].rx_fifo_errors += stats[0].rx_fifo_errors; + stats[N_TX_RINGS].tx_aborted_errors += stats[0].tx_aborted_errors; + stats[N_TX_RINGS].tx_fifo_errors += stats[0].tx_fifo_errors; + spin_unlock(&cp->stat_lock[0]); + + for (i = 0; i < N_TX_RINGS; i++) { + spin_lock(&cp->stat_lock[i]); + stats[N_TX_RINGS].rx_length_errors += + stats[i].rx_length_errors; + stats[N_TX_RINGS].rx_crc_errors += stats[i].rx_crc_errors; + stats[N_TX_RINGS].rx_packets += stats[i].rx_packets; + stats[N_TX_RINGS].tx_packets += stats[i].tx_packets; + stats[N_TX_RINGS].rx_bytes += stats[i].rx_bytes; + stats[N_TX_RINGS].tx_bytes += stats[i].tx_bytes; + stats[N_TX_RINGS].rx_errors += stats[i].rx_errors; + stats[N_TX_RINGS].tx_errors += stats[i].tx_errors; + stats[N_TX_RINGS].rx_dropped += stats[i].rx_dropped; + stats[N_TX_RINGS].tx_dropped += stats[i].tx_dropped; + memset(stats + i, 0, sizeof(struct net_device_stats)); + spin_unlock(&cp->stat_lock[i]); + } + spin_unlock_irqrestore(&cp->stat_lock[N_TX_RINGS], flags); + return stats + N_TX_RINGS; +} + + +static void cas_set_multicast(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + u32 rxcfg, rxcfg_new; + unsigned long flags; + int limit = STOP_TRIES; + + if (!cp->hw_running) + return; + + spin_lock_irqsave(&cp->lock, flags); + rxcfg = readl(cp->regs + REG_MAC_RX_CFG); + + /* disable RX MAC and wait for completion */ + writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG); + while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN) { + if (!limit--) + break; + udelay(10); + } + + /* disable hash filter and wait for completion */ + limit = STOP_TRIES; + rxcfg &= ~(MAC_RX_CFG_PROMISC_EN | MAC_RX_CFG_HASH_FILTER_EN); + writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG); + while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_HASH_FILTER_EN) { + if (!limit--) + break; + udelay(10); + } + + /* program hash filters */ + cp->mac_rx_cfg = rxcfg_new = cas_setup_multicast(cp); + rxcfg |= rxcfg_new; + writel(rxcfg, cp->regs + REG_MAC_RX_CFG); + spin_unlock_irqrestore(&cp->lock, flags); +} + +/* Eventually add support for changing the advertisement + * on autoneg. + */ +static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) +{ + struct cas *cp = netdev_priv(dev); + u16 bmcr; + int full_duplex, speed, pause; + struct ethtool_cmd ecmd; + unsigned long flags; + enum link_state linkstate = link_up; + + if (copy_from_user(&ecmd, ep_user, sizeof(ecmd))) + return -EFAULT; + + switch(ecmd.cmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO }; + + strncpy(info.driver, DRV_MODULE_NAME, + ETHTOOL_BUSINFO_LEN); + strncpy(info.version, DRV_MODULE_VERSION, + ETHTOOL_BUSINFO_LEN); + info.fw_version[0] = '\0'; + strncpy(info.bus_info, pci_name(cp->pdev), + ETHTOOL_BUSINFO_LEN); + info.regdump_len = cp->casreg_len < CAS_MAX_REGS ? + cp->casreg_len : CAS_MAX_REGS; + info.n_stats = CAS_NUM_STAT_KEYS; + if (copy_to_user(ep_user, &info, sizeof(info))) + return -EFAULT; + + return 0; + } + + case ETHTOOL_GSET: + ecmd.advertising = 0; + ecmd.supported = SUPPORTED_Autoneg; + if (cp->cas_flags & CAS_FLAG_1000MB_CAP) { + ecmd.supported |= SUPPORTED_1000baseT_Full; + ecmd.advertising |= ADVERTISED_1000baseT_Full; + } + + /* Record PHY settings if HW is on. */ + spin_lock_irqsave(&cp->lock, flags); + bmcr = 0; + linkstate = cp->lstate; + if (CAS_PHY_MII(cp->phy_type)) { + ecmd.port = PORT_MII; + ecmd.transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ? + XCVR_INTERNAL : XCVR_EXTERNAL; + ecmd.phy_address = cp->phy_addr; + ecmd.advertising |= ADVERTISED_TP | ADVERTISED_MII | + ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + + ecmd.supported |= + (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_TP | SUPPORTED_MII); + + if (cp->hw_running) { + cas_mif_poll(cp, 0); + bmcr = cas_phy_read(cp, MII_BMCR); + cas_read_mii_link_mode(cp, &full_duplex, + &speed, &pause); + cas_mif_poll(cp, 1); + } + + } else { + ecmd.port = PORT_FIBRE; + ecmd.transceiver = XCVR_INTERNAL; + ecmd.phy_address = 0; + ecmd.supported |= SUPPORTED_FIBRE; + ecmd.advertising |= ADVERTISED_FIBRE; + + if (cp->hw_running) { + /* pcs uses the same bits as mii */ + bmcr = readl(cp->regs + REG_PCS_MII_CTRL); + cas_read_pcs_link_mode(cp, &full_duplex, + &speed, &pause); + } + } + spin_unlock_irqrestore(&cp->lock, flags); + + if (bmcr & BMCR_ANENABLE) { + ecmd.advertising |= ADVERTISED_Autoneg; + ecmd.autoneg = AUTONEG_ENABLE; + ecmd.speed = ((speed == 10) ? + SPEED_10 : + ((speed == 1000) ? + SPEED_1000 : SPEED_100)); + ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd.autoneg = AUTONEG_DISABLE; + ecmd.speed = + (bmcr & CAS_BMCR_SPEED1000) ? + SPEED_1000 : + ((bmcr & BMCR_SPEED100) ? SPEED_100: + SPEED_10); + ecmd.duplex = + (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; + } + if (linkstate != link_up) { + /* Force these to "unknown" if the link is not up and + * autonogotiation in enabled. We can set the link + * speed to 0, but not ecmd.duplex, + * because its legal values are 0 and 1. Ethtool will + * print the value reported in parentheses after the + * word "Unknown" for unrecognized values. + * + * If in forced mode, we report the speed and duplex + * settings that we configured. + */ + if (cp->link_cntl & BMCR_ANENABLE) { + ecmd.speed = 0; + ecmd.duplex = 0xff; + } else { + ecmd.speed = SPEED_10; + if (cp->link_cntl & BMCR_SPEED100) { + ecmd.speed = SPEED_100; + } else if (cp->link_cntl & CAS_BMCR_SPEED1000) { + ecmd.speed = SPEED_1000; + } + ecmd.duplex = (cp->link_cntl & BMCR_FULLDPLX)? + DUPLEX_FULL : DUPLEX_HALF; + } + } + if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) + return -EFAULT; + return 0; + + case ETHTOOL_SSET: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Verify the settings we care about. */ + if (ecmd.autoneg != AUTONEG_ENABLE && + ecmd.autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (ecmd.autoneg == AUTONEG_DISABLE && + ((ecmd.speed != SPEED_1000 && + ecmd.speed != SPEED_100 && + ecmd.speed != SPEED_10) || + (ecmd.duplex != DUPLEX_HALF && + ecmd.duplex != DUPLEX_FULL))) + return -EINVAL; + + /* Apply settings and restart link process. */ + spin_lock_irqsave(&cp->lock, flags); + cas_begin_auto_negotiation(cp, &ecmd); + spin_unlock_irqrestore(&cp->lock, flags); + return 0; + + case ETHTOOL_NWAY_RST: + if ((cp->link_cntl & BMCR_ANENABLE) == 0) + return -EINVAL; + + /* Restart link process. */ + spin_lock_irqsave(&cp->lock, flags); + cas_begin_auto_negotiation(cp, NULL); + spin_unlock_irqrestore(&cp->lock, flags); + + return 0; + + case ETHTOOL_GWOL: + case ETHTOOL_SWOL: + break; /* doesn't exist */ + + /* get link status */ + case ETHTOOL_GLINK: { + struct ethtool_value edata = { cmd: ETHTOOL_GLINK }; + + edata.data = (cp->lstate == link_up); + if (copy_to_user(ep_user, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + + /* get message-level */ + case ETHTOOL_GMSGLVL: { + struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL }; + + edata.data = cp->msg_enable; + if (copy_to_user(ep_user, &edata, sizeof(edata))) + return -EFAULT; + return 0; + } + + /* set message-level */ + case ETHTOOL_SMSGLVL: { + struct ethtool_value edata; + + if (!capable(CAP_NET_ADMIN)) { + return (-EPERM); + } + if (copy_from_user(&edata, ep_user, sizeof(edata))) + return -EFAULT; + cp->msg_enable = edata.data; + return 0; + } + + case ETHTOOL_GREGS: { + struct ethtool_regs edata; + u8 *ptr; + int len = cp->casreg_len < CAS_MAX_REGS ? + cp->casreg_len: CAS_MAX_REGS; + + if (copy_from_user(&edata, ep_user, sizeof (edata))) + return -EFAULT; + + if (edata.len > len) + edata.len = len; + edata.version = 0; + if (copy_to_user (ep_user, &edata, sizeof(edata))) + return -EFAULT; + + /* cas_get_regs handles locks (cp->lock). */ + ptr = cas_get_regs(cp); + if (ptr == NULL) + return -ENOMEM; + if (copy_to_user(ep_user + sizeof (edata), ptr, edata.len)) + return -EFAULT; + + kfree(ptr); + return (0); + } + case ETHTOOL_GSTRINGS: { + struct ethtool_gstrings edata; + int len; + + if (copy_from_user(&edata, ep_user, sizeof(edata))) + return -EFAULT; + + len = edata.len; + switch(edata.string_set) { + case ETH_SS_STATS: + edata.len = (len < CAS_NUM_STAT_KEYS) ? + len : CAS_NUM_STAT_KEYS; + if (copy_to_user(ep_user, &edata, sizeof(edata))) + return -EFAULT; + + if (copy_to_user(ep_user + sizeof(edata), + ðtool_cassini_statnames, + (edata.len * ETH_GSTRING_LEN))) + return -EFAULT; + return 0; + default: + return -EINVAL; + } + } + case ETHTOOL_GSTATS: { + int i = 0; + u64 *tmp; + struct ethtool_stats edata; + struct net_device_stats *stats; + int len; + + if (copy_from_user(&edata, ep_user, sizeof(edata))) + return -EFAULT; + + len = edata.n_stats; + stats = cas_get_stats(cp->dev); + edata.cmd = ETHTOOL_GSTATS; + edata.n_stats = (len < CAS_NUM_STAT_KEYS) ? + len : CAS_NUM_STAT_KEYS; + if (copy_to_user(ep_user, &edata, sizeof (edata))) + return -EFAULT; + + tmp = kmalloc(sizeof(u64)*CAS_NUM_STAT_KEYS, GFP_KERNEL); + if (tmp) { + tmp[i++] = stats->collisions; + tmp[i++] = stats->rx_bytes; + tmp[i++] = stats->rx_crc_errors; + tmp[i++] = stats->rx_dropped; + tmp[i++] = stats->rx_errors; + tmp[i++] = stats->rx_fifo_errors; + tmp[i++] = stats->rx_frame_errors; + tmp[i++] = stats->rx_length_errors; + tmp[i++] = stats->rx_over_errors; + tmp[i++] = stats->rx_packets; + tmp[i++] = stats->tx_aborted_errors; + tmp[i++] = stats->tx_bytes; + tmp[i++] = stats->tx_dropped; + tmp[i++] = stats->tx_errors; + tmp[i++] = stats->tx_fifo_errors; + tmp[i++] = stats->tx_packets; + BUG_ON(i != CAS_NUM_STAT_KEYS); + + i = copy_to_user(ep_user + sizeof(edata), + tmp, sizeof(u64)*edata.n_stats); + kfree(tmp); + } else { + return -ENOMEM; + } + if (i) + return -EFAULT; + return 0; + } + } + + return -EOPNOTSUPP; +} + +static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct cas *cp = netdev_priv(dev); + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + unsigned long flags; + int rc = -EOPNOTSUPP; + + /* Hold the PM semaphore while doing ioctl's or we may collide + * with open/close and power management and oops. + */ + down(&cp->pm_sem); + switch (cmd) { + case SIOCETHTOOL: + rc = cas_ethtool_ioctl(dev, ifr->ifr_data); + break; + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + data->phy_id = cp->phy_addr; + /* Fallthrough... */ + + case SIOCGMIIREG: /* Read MII PHY register. */ + spin_lock_irqsave(&cp->lock, flags); + cas_mif_poll(cp, 0); + data->val_out = cas_phy_read(cp, data->reg_num & 0x1f); + cas_mif_poll(cp, 1); + spin_unlock_irqrestore(&cp->lock, flags); + rc = 0; + break; + + case SIOCSMIIREG: /* Write MII PHY register. */ + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + break; + } + spin_lock_irqsave(&cp->lock, flags); + cas_mif_poll(cp, 0); + rc = cas_phy_write(cp, data->reg_num & 0x1f, data->val_in); + cas_mif_poll(cp, 1); + spin_unlock_irqrestore(&cp->lock, flags); + break; + default: + break; + }; + + up(&cp->pm_sem); + return rc; +} + +static int __devinit cas_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + static int cas_version_printed = 0; + unsigned long casreg_base, casreg_len; + struct net_device *dev; + struct cas *cp; + int i, err, pci_using_dac; + u16 pci_cmd; + u8 orig_cacheline_size = 0, cas_cacheline_size = 0; + + if (cas_version_printed++ == 0) + printk(KERN_INFO "%s", version); + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR PFX "Cannot enable PCI device, " + "aborting.\n"); + return err; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX "Cannot find proper PCI device " + "base address, aborting.\n"); + err = -ENODEV; + goto err_out_disable_pdev; + } + + dev = alloc_etherdev(sizeof(*cp)); + if (!dev) { + printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + err = -ENOMEM; + goto err_out_disable_pdev; + } + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + err = pci_request_regions(pdev, dev->name); + if (err) { + printk(KERN_ERR PFX "Cannot obtain PCI resources, " + "aborting.\n"); + goto err_out_free_netdev; + } + pci_set_master(pdev); + + /* we must always turn on parity response or else parity + * doesn't get generated properly. disable SERR/PERR as well. + * in addition, we want to turn MWI on. + */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); + pci_cmd &= ~PCI_COMMAND_SERR; + pci_cmd |= PCI_COMMAND_PARITY; + pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); + pci_set_mwi(pdev); + /* + * On some architectures, the default cache line size set + * by pci_set_mwi reduces perforamnce. We have to increase + * it for this case. To start, we'll print some configuration + * data. + */ +#if 1 + pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, + &orig_cacheline_size); + if (orig_cacheline_size < CAS_PREF_CACHELINE_SIZE) { + cas_cacheline_size = + (CAS_PREF_CACHELINE_SIZE < SMP_CACHE_BYTES) ? + CAS_PREF_CACHELINE_SIZE : SMP_CACHE_BYTES; + if (pci_write_config_byte(pdev, + PCI_CACHE_LINE_SIZE, + cas_cacheline_size)) { + printk(KERN_ERR PFX "Could not set PCI cache " + "line size\n"); + goto err_write_cacheline; + } + } +#endif + + + /* Configure DMA attributes. */ + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + pci_using_dac = 1; + err = pci_set_consistent_dma_mask(pdev, + DMA_64BIT_MASK); + if (err < 0) { + printk(KERN_ERR PFX "Unable to obtain 64-bit DMA " + "for consistent allocations\n"); + goto err_out_free_res; + } + + } else { + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + printk(KERN_ERR PFX "No usable DMA configuration, " + "aborting.\n"); + goto err_out_free_res; + } + pci_using_dac = 0; + } + + casreg_base = pci_resource_start(pdev, 0); + casreg_len = pci_resource_len(pdev, 0); + + cp = netdev_priv(dev); + cp->pdev = pdev; +#if 1 + /* A value of 0 indicates we never explicitly set it */ + cp->orig_cacheline_size = cas_cacheline_size ? orig_cacheline_size: 0; +#endif + cp->dev = dev; + cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE : + cassini_debug; + + cp->link_transition = LINK_TRANSITION_UNKNOWN; + cp->link_transition_jiffies_valid = 0; + + spin_lock_init(&cp->lock); + spin_lock_init(&cp->rx_inuse_lock); + spin_lock_init(&cp->rx_spare_lock); + for (i = 0; i < N_TX_RINGS; i++) { + spin_lock_init(&cp->stat_lock[i]); + spin_lock_init(&cp->tx_lock[i]); + } + spin_lock_init(&cp->stat_lock[N_TX_RINGS]); + init_MUTEX(&cp->pm_sem); + + init_timer(&cp->link_timer); + cp->link_timer.function = cas_link_timer; + cp->link_timer.data = (unsigned long) cp; + +#if 1 + /* Just in case the implementation of atomic operations + * change so that an explicit initialization is necessary. + */ + atomic_set(&cp->reset_task_pending, 0); + atomic_set(&cp->reset_task_pending_all, 0); + atomic_set(&cp->reset_task_pending_spare, 0); + atomic_set(&cp->reset_task_pending_mtu, 0); +#endif + INIT_WORK(&cp->reset_task, cas_reset_task, cp); + + /* Default link parameters */ + if (link_mode >= 0 && link_mode <= 6) + cp->link_cntl = link_modes[link_mode]; + else + cp->link_cntl = BMCR_ANENABLE; + cp->lstate = link_down; + cp->link_transition = LINK_TRANSITION_LINK_DOWN; + netif_carrier_off(cp->dev); + cp->timer_ticks = 0; + + /* give us access to cassini registers */ + cp->regs = ioremap(casreg_base, casreg_len); + if (cp->regs == 0UL) { + printk(KERN_ERR PFX "Cannot map device registers, " + "aborting.\n"); + goto err_out_free_res; + } + cp->casreg_len = casreg_len; + + pci_save_state(pdev); + cas_check_pci_invariants(cp); + cas_hard_reset(cp); + cas_reset(cp, 0); + if (cas_check_invariants(cp)) + goto err_out_iounmap; + + cp->init_block = (struct cas_init_block *) + pci_alloc_consistent(pdev, sizeof(struct cas_init_block), + &cp->block_dvma); + if (!cp->init_block) { + printk(KERN_ERR PFX "Cannot allocate init block, " + "aborting.\n"); + goto err_out_iounmap; + } + + for (i = 0; i < N_TX_RINGS; i++) + cp->init_txds[i] = cp->init_block->txds[i]; + + for (i = 0; i < N_RX_DESC_RINGS; i++) + cp->init_rxds[i] = cp->init_block->rxds[i]; + + for (i = 0; i < N_RX_COMP_RINGS; i++) + cp->init_rxcs[i] = cp->init_block->rxcs[i]; + + for (i = 0; i < N_RX_FLOWS; i++) + skb_queue_head_init(&cp->rx_flows[i]); + + dev->open = cas_open; + dev->stop = cas_close; + dev->hard_start_xmit = cas_start_xmit; + dev->get_stats = cas_get_stats; + dev->set_multicast_list = cas_set_multicast; + dev->do_ioctl = cas_ioctl; + dev->tx_timeout = cas_tx_timeout; + dev->watchdog_timeo = CAS_TX_TIMEOUT; + dev->change_mtu = cas_change_mtu; +#ifdef USE_NAPI + dev->poll = cas_poll; + dev->weight = 64; +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = cas_netpoll; +#endif + dev->irq = pdev->irq; + dev->dma = 0; + + /* Cassini features. */ + if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0) + dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + + if (register_netdev(dev)) { + printk(KERN_ERR PFX "Cannot register net device, " + "aborting.\n"); + goto err_out_free_consistent; + } + + i = readl(cp->regs + REG_BIM_CFG); + printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) " + "Ethernet[%d] ", dev->name, + (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "", + (i & BIM_CFG_32BIT) ? "32" : "64", + (i & BIM_CFG_66MHZ) ? "66" : "33", + (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq); + + for (i = 0; i < 6; i++) + printk("%2.2x%c", dev->dev_addr[i], + i == 5 ? ' ' : ':'); + printk("\n"); + + pci_set_drvdata(pdev, dev); + cp->hw_running = 1; + cas_entropy_reset(cp); + cas_phy_init(cp); + cas_begin_auto_negotiation(cp, NULL); + return 0; + +err_out_free_consistent: + pci_free_consistent(pdev, sizeof(struct cas_init_block), + cp->init_block, cp->block_dvma); + +err_out_iounmap: + down(&cp->pm_sem); + if (cp->hw_running) + cas_shutdown(cp); + up(&cp->pm_sem); + + iounmap((void *) cp->regs); + + +err_out_free_res: + pci_release_regions(pdev); + +err_write_cacheline: + /* Try to restore it in case the error occured after we + * set it. + */ + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, orig_cacheline_size); + +err_out_free_netdev: + free_netdev(dev); + +err_out_disable_pdev: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + return -ENODEV; +} + +static void __devexit cas_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct cas *cp; + if (!dev) + return; + + cp = netdev_priv(dev); + unregister_netdev(dev); + + down(&cp->pm_sem); + flush_scheduled_work(); + if (cp->hw_running) + cas_shutdown(cp); + up(&cp->pm_sem); + +#if 1 + if (cp->orig_cacheline_size) { + /* Restore the cache line size if we had modified + * it. + */ + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + cp->orig_cacheline_size); + } +#endif + pci_free_consistent(pdev, sizeof(struct cas_init_block), + cp->init_block, cp->block_dvma); + iounmap((void *) cp->regs); + free_netdev(dev); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +#ifdef CONFIG_PM +static int cas_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct cas *cp = netdev_priv(dev); + unsigned long flags; + + /* We hold the PM semaphore during entire driver + * sleep time + */ + down(&cp->pm_sem); + + /* If the driver is opened, we stop the DMA */ + if (cp->opened) { + netif_device_detach(dev); + + cas_lock_all_save(cp, flags); + + /* We can set the second arg of cas_reset to 0 + * because on resume, we'll call cas_init_hw with + * its second arg set so that autonegotiation is + * restarted. + */ + cas_reset(cp, 0); + cas_clean_rings(cp); + cas_unlock_all_restore(cp, flags); + } + + if (cp->hw_running) + cas_shutdown(cp); + + return 0; +} + +static int cas_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct cas *cp = netdev_priv(dev); + + printk(KERN_INFO "%s: resuming\n", dev->name); + + cas_hard_reset(cp); + if (cp->opened) { + unsigned long flags; + cas_lock_all_save(cp, flags); + cas_reset(cp, 0); + cp->hw_running = 1; + cas_clean_rings(cp); + cas_init_hw(cp, 1); + cas_unlock_all_restore(cp, flags); + + netif_device_attach(dev); + } + up(&cp->pm_sem); + return 0; +} +#endif /* CONFIG_PM */ + +static struct pci_driver cas_driver = { + .name = DRV_MODULE_NAME, + .id_table = cas_pci_tbl, + .probe = cas_init_one, + .remove = __devexit_p(cas_remove_one), +#ifdef CONFIG_PM + .suspend = cas_suspend, + .resume = cas_resume +#endif +}; + +static int __init cas_init(void) +{ + if (linkdown_timeout > 0) + link_transition_timeout = linkdown_timeout * HZ; + else + link_transition_timeout = 0; + + return pci_module_init(&cas_driver); +} + +static void __exit cas_cleanup(void) +{ + pci_unregister_driver(&cas_driver); +} + +module_init(cas_init); +module_exit(cas_cleanup); diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h new file mode 100644 index 0000000..88063ef --- /dev/null +++ b/drivers/net/cassini.h @@ -0,0 +1,4425 @@ +/* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $ + * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver. + * + * Copyright (C) 2004 Sun Microsystems Inc. + * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com) + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * vendor id: 0x108E (Sun Microsystems, Inc.) + * device id: 0xabba (Cassini) + * revision ids: 0x01 = Cassini + * 0x02 = Cassini rev 2 + * 0x10 = Cassini+ + * 0x11 = Cassini+ 0.2u + * + * vendor id: 0x100b (National Semiconductor) + * device id: 0x0035 (DP83065/Saturn) + * revision ids: 0x30 = Saturn B2 + * + * rings are all offset from 0. + * + * there are two clock domains: + * PCI: 33/66MHz clock + * chip: 125MHz clock + */ + +#ifndef _CASSINI_H +#define _CASSINI_H + +/* cassini register map: 2M memory mapped in 32-bit memory space accessible as + * 32-bit words. there is no i/o port access. REG_ addresses are + * shared between cassini and cassini+. REG_PLUS_ addresses only + * appear in cassini+. REG_MINUS_ addresses only appear in cassini. + */ +#define CAS_ID_REV2 0x02 +#define CAS_ID_REVPLUS 0x10 +#define CAS_ID_REVPLUS02u 0x11 +#define CAS_ID_REVSATURNB2 0x30 + +/** global resources **/ + +/* this register sets the weights for the weighted round robin arbiter. e.g., + * if rx weight == 1 and tx weight == 0, rx == 2x tx transfer credit + * for its next turn to access the pci bus. + * map: 0x0 = x1, 0x1 = x2, 0x2 = x4, 0x3 = x8 + * DEFAULT: 0x0, SIZE: 5 bits + */ +#define REG_CAWR 0x0004 /* core arbitration weight */ +#define CAWR_RX_DMA_WEIGHT_SHIFT 0 +#define CAWR_RX_DMA_WEIGHT_MASK 0x03 /* [0:1] */ +#define CAWR_TX_DMA_WEIGHT_SHIFT 2 +#define CAWR_TX_DMA_WEIGHT_MASK 0x0C /* [3:2] */ +#define CAWR_RR_DIS 0x10 /* [4] */ + +/* if enabled, BIM can send bursts across PCI bus > cacheline size. burst + * sizes determined by length of packet or descriptor transfer and the + * max length allowed by the target. + * DEFAULT: 0x0, SIZE: 1 bit + */ +#define REG_INF_BURST 0x0008 /* infinite burst enable reg */ +#define INF_BURST_EN 0x1 /* enable */ + +/* top level interrupts [0-9] are auto-cleared to 0 when the status + * register is read. second level interrupts [13 - 18] are cleared at + * the source. tx completion register 3 is replicated in [19 - 31] + * DEFAULT: 0x00000000, SIZE: 29 bits + */ +#define REG_INTR_STATUS 0x000C /* interrupt status register */ +#define INTR_TX_INTME 0x00000001 /* frame w/ INT ME desc bit set + xferred from host queue to + TX FIFO */ +#define INTR_TX_ALL 0x00000002 /* all xmit frames xferred into + TX FIFO. i.e., + TX Kick == TX complete. if + PACED_MODE set, then TX FIFO + also empty */ +#define INTR_TX_DONE 0x00000004 /* any frame xferred into tx + FIFO */ +#define INTR_TX_TAG_ERROR 0x00000008 /* TX FIFO tag framing + corrupted. FATAL ERROR */ +#define INTR_RX_DONE 0x00000010 /* at least 1 frame xferred + from RX FIFO to host mem. + RX completion reg updated. + may be delayed by recv + intr blanking. */ +#define INTR_RX_BUF_UNAVAIL 0x00000020 /* no more receive buffers. + RX Kick == RX complete */ +#define INTR_RX_TAG_ERROR 0x00000040 /* RX FIFO tag framing + corrupted. FATAL ERROR */ +#define INTR_RX_COMP_FULL 0x00000080 /* no more room in completion + ring to post descriptors. + RX complete head incr to + almost reach RX complete + tail */ +#define INTR_RX_BUF_AE 0x00000100 /* less than the + programmable threshold # + of free descr avail for + hw use */ +#define INTR_RX_COMP_AF 0x00000200 /* less than the + programmable threshold # + of descr spaces for hw + use in completion descr + ring */ +#define INTR_RX_LEN_MISMATCH 0x00000400 /* len field from MAC != + len of non-reassembly pkt + from fifo during DMA or + header parser provides TCP + header and payload size > + MAC packet size. + FATAL ERROR */ +#define INTR_SUMMARY 0x00001000 /* summary interrupt bit. this + bit will be set if an interrupt + generated on the pci bus. useful + when driver is polling for + interrupts */ +#define INTR_PCS_STATUS 0x00002000 /* PCS interrupt status register */ +#define INTR_TX_MAC_STATUS 0x00004000 /* TX MAC status register has at + least 1 unmasked interrupt set */ +#define INTR_RX_MAC_STATUS 0x00008000 /* RX MAC status register has at + least 1 unmasked interrupt set */ +#define INTR_MAC_CTRL_STATUS 0x00010000 /* MAC control status register has + at least 1 unmasked interrupt + set */ +#define INTR_MIF_STATUS 0x00020000 /* MIF status register has at least + 1 unmasked interrupt set */ +#define INTR_PCI_ERROR_STATUS 0x00040000 /* PCI error status register in the + BIF has at least 1 unmasked + interrupt set */ +#define INTR_TX_COMP_3_MASK 0xFFF80000 /* mask for TX completion + 3 reg data */ +#define INTR_TX_COMP_3_SHIFT 19 +#define INTR_ERROR_MASK (INTR_MIF_STATUS | INTR_PCI_ERROR_STATUS | \ + INTR_PCS_STATUS | INTR_RX_LEN_MISMATCH | \ + INTR_TX_MAC_STATUS | INTR_RX_MAC_STATUS | \ + INTR_TX_TAG_ERROR | INTR_RX_TAG_ERROR | \ + INTR_MAC_CTRL_STATUS) + +/* determines which status events will cause an interrupt. layout same + * as REG_INTR_STATUS. + * DEFAULT: 0xFFFFFFFF, SIZE: 16 bits + */ +#define REG_INTR_MASK 0x0010 /* Interrupt mask */ + +/* top level interrupt bits that are cleared during read of REG_INTR_STATUS_ALIAS. + * useful when driver is polling for interrupts. layout same as REG_INTR_MASK. + * DEFAULT: 0x00000000, SIZE: 12 bits + */ +#define REG_ALIAS_CLEAR 0x0014 /* alias clear mask + (used w/ status alias) */ +/* same as REG_INTR_STATUS except that only bits cleared are those selected by + * REG_ALIAS_CLEAR + * DEFAULT: 0x00000000, SIZE: 29 bits + */ +#define REG_INTR_STATUS_ALIAS 0x001C /* interrupt status alias + (selective clear) */ + +/* DEFAULT: 0x0, SIZE: 3 bits */ +#define REG_PCI_ERR_STATUS 0x1000 /* PCI error status */ +#define PCI_ERR_BADACK 0x01 /* reserved in Cassini+. + set if no ACK64# during ABS64 cycle + in Cassini. */ +#define PCI_ERR_DTRTO 0x02 /* delayed xaction timeout. set if + no read retry after 2^15 clocks */ +#define PCI_ERR_OTHER 0x04 /* other PCI errors */ +#define PCI_ERR_BIM_DMA_WRITE 0x08 /* BIM received 0 count DMA write req. + unused in Cassini. */ +#define PCI_ERR_BIM_DMA_READ 0x10 /* BIM received 0 count DMA read req. + unused in Cassini. */ +#define PCI_ERR_BIM_DMA_TIMEOUT 0x20 /* BIM received 255 retries during + DMA. unused in cassini. */ + +/* mask for PCI status events that will set PCI_ERR_STATUS. if cleared, event + * causes an interrupt to be generated. + * DEFAULT: 0x7, SIZE: 3 bits + */ +#define REG_PCI_ERR_STATUS_MASK 0x1004 /* PCI Error status mask */ + +/* used to configure PCI related parameters that are not in PCI config space. + * DEFAULT: 0bxx000, SIZE: 5 bits + */ +#define REG_BIM_CFG 0x1008 /* BIM Configuration */ +#define BIM_CFG_RESERVED0 0x001 /* reserved */ +#define BIM_CFG_RESERVED1 0x002 /* reserved */ +#define BIM_CFG_64BIT_DISABLE 0x004 /* disable 64-bit mode */ +#define BIM_CFG_66MHZ 0x008 /* (ro) 1 = 66MHz, 0 = < 66MHz */ +#define BIM_CFG_32BIT 0x010 /* (ro) 1 = 32-bit slot, 0 = 64-bit */ +#define BIM_CFG_DPAR_INTR_ENABLE 0x020 /* detected parity err enable */ +#define BIM_CFG_RMA_INTR_ENABLE 0x040 /* master abort intr enable */ +#define BIM_CFG_RTA_INTR_ENABLE 0x080 /* target abort intr enable */ +#define BIM_CFG_RESERVED2 0x100 /* reserved */ +#define BIM_CFG_BIM_DISABLE 0x200 /* stop BIM DMA. use before global + reset. reserved in Cassini. */ +#define BIM_CFG_BIM_STATUS 0x400 /* (ro) 1 = BIM DMA suspended. + reserved in Cassini. */ +#define BIM_CFG_PERROR_BLOCK 0x800 /* block PERR# to pci bus. def: 0. + reserved in Cassini. */ + +/* DEFAULT: 0x00000000, SIZE: 32 bits */ +#define REG_BIM_DIAG 0x100C /* BIM Diagnostic */ +#define BIM_DIAG_MSTR_SM_MASK 0x3FFFFF00 /* PCI master controller state + machine bits [21:0] */ +#define BIM_DIAG_BRST_SM_MASK 0x7F /* PCI burst controller state + machine bits [6:0] */ + +/* writing to SW_RESET_TX and SW_RESET_RX will issue a global + * reset. poll until TX and RX read back as 0's for completion. + */ +#define REG_SW_RESET 0x1010 /* Software reset */ +#define SW_RESET_TX 0x00000001 /* reset TX DMA engine. poll until + cleared to 0. */ +#define SW_RESET_RX 0x00000002 /* reset RX DMA engine. poll until + cleared to 0. */ +#define SW_RESET_RSTOUT 0x00000004 /* force RSTOUT# pin active (low). + resets PHY and anything else + connected to RSTOUT#. RSTOUT# + is also activated by local PCI + reset when hot-swap is being + done. */ +#define SW_RESET_BLOCK_PCS_SLINK 0x00000008 /* if a global reset is done with + this bit set, PCS and SLINK + modules won't be reset. + i.e., link won't drop. */ +#define SW_RESET_BREQ_SM_MASK 0x00007F00 /* breq state machine [6:0] */ +#define SW_RESET_PCIARB_SM_MASK 0x00070000 /* pci arbitration state bits: + 0b000: ARB_IDLE1 + 0b001: ARB_IDLE2 + 0b010: ARB_WB_ACK + 0b011: ARB_WB_WAT + 0b100: ARB_RB_ACK + 0b101: ARB_RB_WAT + 0b110: ARB_RB_END + 0b111: ARB_WB_END */ +#define SW_RESET_RDPCI_SM_MASK 0x00300000 /* read pci state bits: + 0b00: RD_PCI_WAT + 0b01: RD_PCI_RDY + 0b11: RD_PCI_ACK */ +#define SW_RESET_RDARB_SM_MASK 0x00C00000 /* read arbitration state bits: + 0b00: AD_IDL_RX + 0b01: AD_ACK_RX + 0b10: AD_ACK_TX + 0b11: AD_IDL_TX */ +#define SW_RESET_WRPCI_SM_MASK 0x06000000 /* write pci state bits + 0b00: WR_PCI_WAT + 0b01: WR_PCI_RDY + 0b11: WR_PCI_ACK */ +#define SW_RESET_WRARB_SM_MASK 0x38000000 /* write arbitration state bits: + 0b000: ARB_IDLE1 + 0b001: ARB_IDLE2 + 0b010: ARB_TX_ACK + 0b011: ARB_TX_WAT + 0b100: ARB_RX_ACK + 0b110: ARB_RX_WAT */ + +/* Cassini only. 64-bit register used to check PCI datapath. when read, + * value written has both lower and upper 32-bit halves rotated to the right + * one bit position. e.g., FFFFFFFF FFFFFFFF -> 7FFFFFFF 7FFFFFFF + */ +#define REG_MINUS_BIM_DATAPATH_TEST 0x1018 /* Cassini: BIM datapath test + Cassini+: reserved */ + +/* output enables are provided for each device's chip select and for the rest + * of the outputs from cassini to its local bus devices. two sw programmable + * bits are connected to general purpus control/status bits. + * DEFAULT: 0x7 + */ +#define REG_BIM_LOCAL_DEV_EN 0x1020 /* BIM local device + output EN. default: 0x7 */ +#define BIM_LOCAL_DEV_PAD 0x01 /* address bus, RW signal, and + OE signal output enable on the + local bus interface. these + are shared between both local + bus devices. tristate when 0. */ +#define BIM_LOCAL_DEV_PROM 0x02 /* PROM chip select */ +#define BIM_LOCAL_DEV_EXT 0x04 /* secondary local bus device chip + select output enable */ +#define BIM_LOCAL_DEV_SOFT_0 0x08 /* sw programmable ctrl bit 0 */ +#define BIM_LOCAL_DEV_SOFT_1 0x10 /* sw programmable ctrl bit 1 */ +#define BIM_LOCAL_DEV_HW_RESET 0x20 /* internal hw reset. Cassini+ only. */ + +/* access 24 entry BIM read and write buffers. put address in REG_BIM_BUFFER_ADDR + * and read/write from/to it REG_BIM_BUFFER_DATA_LOW and _DATA_HI. + * _DATA_HI should be the last access of the sequence. + * DEFAULT: undefined + */ +#define REG_BIM_BUFFER_ADDR 0x1024 /* BIM buffer address. for + purposes. */ +#define BIM_BUFFER_ADDR_MASK 0x3F /* index (0 - 23) of buffer */ +#define BIM_BUFFER_WR_SELECT 0x40 /* write buffer access = 1 + read buffer access = 0 */ +/* DEFAULT: undefined */ +#define REG_BIM_BUFFER_DATA_LOW 0x1028 /* BIM buffer data low */ +#define REG_BIM_BUFFER_DATA_HI 0x102C /* BIM buffer data high */ + +/* set BIM_RAM_BIST_START to start built-in self test for BIM read buffer. + * bit auto-clears when done with status read from _SUMMARY and _PASS bits. + */ +#define REG_BIM_RAM_BIST 0x102C /* BIM RAM (read buffer) BIST + control/status */ +#define BIM_RAM_BIST_RD_START 0x01 /* start BIST for BIM read buffer */ +#define BIM_RAM_BIST_WR_START 0x02 /* start BIST for BIM write buffer. + Cassini only. reserved in + Cassini+. */ +#define BIM_RAM_BIST_RD_PASS 0x04 /* summary BIST pass status for read + buffer. */ +#define BIM_RAM_BIST_WR_PASS 0x08 /* summary BIST pass status for write + buffer. Cassini only. reserved + in Cassini+. */ +#define BIM_RAM_BIST_RD_LOW_PASS 0x10 /* read low bank passes BIST */ +#define BIM_RAM_BIST_RD_HI_PASS 0x20 /* read high bank passes BIST */ +#define BIM_RAM_BIST_WR_LOW_PASS 0x40 /* write low bank passes BIST. + Cassini only. reserved in + Cassini+. */ +#define BIM_RAM_BIST_WR_HI_PASS 0x80 /* write high bank passes BIST. + Cassini only. reserved in + Cassini+. */ + +/* ASUN: i'm not sure what this does as it's not in the spec. + * DEFAULT: 0xFC + */ +#define REG_BIM_DIAG_MUX 0x1030 /* BIM diagnostic probe mux + select register */ + +/* enable probe monitoring mode and select data appearing on the P_A* bus. bit + * values for _SEL_HI_MASK and _SEL_LOW_MASK: + * 0x0: internal probe[7:0] (pci arb state, wtc empty w, wtc full w, wtc empty w, + * wtc empty r, post pci) + * 0x1: internal probe[15:8] (pci wbuf comp, pci wpkt comp, pci rbuf comp, + * pci rpkt comp, txdma wr req, txdma wr ack, + * txdma wr rdy, txdma wr xfr done) + * 0x2: internal probe[23:16] (txdma rd req, txdma rd ack, txdma rd rdy, rxdma rd, + * rd arb state, rd pci state) + * 0x3: internal probe[31:24] (rxdma req, rxdma ack, rxdma rdy, wrarb state, + * wrpci state) + * 0x4: pci io probe[7:0] 0x5: pci io probe[15:8] + * 0x6: pci io probe[23:16] 0x7: pci io probe[31:24] + * 0x8: pci io probe[39:32] 0x9: pci io probe[47:40] + * 0xa: pci io probe[55:48] 0xb: pci io probe[63:56] + * the following are not available in Cassini: + * 0xc: rx probe[7:0] 0xd: tx probe[7:0] + * 0xe: hp probe[7:0] 0xf: mac probe[7:0] + */ +#define REG_PLUS_PROBE_MUX_SELECT 0x1034 /* Cassini+: PROBE MUX SELECT */ +#define PROBE_MUX_EN 0x80000000 /* allow probe signals to be + driven on local bus P_A[15:0] + for debugging */ +#define PROBE_MUX_SUB_MUX_MASK 0x0000FF00 /* select sub module probe signals: + 0x03 = mac[1:0] + 0x0C = rx[1:0] + 0x30 = tx[1:0] + 0xC0 = hp[1:0] */ +#define PROBE_MUX_SEL_HI_MASK 0x000000F0 /* select which module to appear + on P_A[15:8]. see above for + values. */ +#define PROBE_MUX_SEL_LOW_MASK 0x0000000F /* select which module to appear + on P_A[7:0]. see above for + values. */ + +/* values mean the same thing as REG_INTR_MASK excep that it's for INTB. + DEFAULT: 0x1F */ +#define REG_PLUS_INTR_MASK_1 0x1038 /* Cassini+: interrupt mask + register 2 for INTB */ +#define REG_PLUS_INTRN_MASK(x) (REG_PLUS_INTR_MASK_1 + ((x) - 1)*16) +/* bits correspond to both _MASK and _STATUS registers. _ALT corresponds to + * all of the alternate (2-4) INTR registers while _1 corresponds to only + * _MASK_1 and _STATUS_1 registers. + * DEFAULT: 0x7 for MASK registers, 0x0 for ALIAS_CLEAR registers + */ +#define INTR_RX_DONE_ALT 0x01 +#define INTR_RX_COMP_FULL_ALT 0x02 +#define INTR_RX_COMP_AF_ALT 0x04 +#define INTR_RX_BUF_UNAVAIL_1 0x08 +#define INTR_RX_BUF_AE_1 0x10 /* almost empty */ +#define INTRN_MASK_RX_EN 0x80 +#define INTRN_MASK_CLEAR_ALL (INTR_RX_DONE_ALT | \ + INTR_RX_COMP_FULL_ALT | \ + INTR_RX_COMP_AF_ALT | \ + INTR_RX_BUF_UNAVAIL_1 | \ + INTR_RX_BUF_AE_1) +#define REG_PLUS_INTR_STATUS_1 0x103C /* Cassini+: interrupt status + register 2 for INTB. default: 0x1F */ +#define REG_PLUS_INTRN_STATUS(x) (REG_PLUS_INTR_STATUS_1 + ((x) - 1)*16) +#define INTR_STATUS_ALT_INTX_EN 0x80 /* generate INTX when one of the + flags are set. enables desc ring. */ + +#define REG_PLUS_ALIAS_CLEAR_1 0x1040 /* Cassini+: alias clear mask + register 2 for INTB */ +#define REG_PLUS_ALIASN_CLEAR(x) (REG_PLUS_ALIAS_CLEAR_1 + ((x) - 1)*16) + +#define REG_PLUS_INTR_STATUS_ALIAS_1 0x1044 /* Cassini+: interrupt status + register alias 2 for INTB */ +#define REG_PLUS_INTRN_STATUS_ALIAS(x) (REG_PLUS_INTR_STATUS_ALIAS_1 + ((x) - 1)*16) + +#define REG_SATURN_PCFG 0x106c /* pin configuration register for + integrated macphy */ + +#define SATURN_PCFG_TLA 0x00000001 /* 1 = phy actled */ +#define SATURN_PCFG_FLA 0x00000002 /* 1 = phy link10led */ +#define SATURN_PCFG_CLA 0x00000004 /* 1 = phy link100led */ +#define SATURN_PCFG_LLA 0x00000008 /* 1 = phy link1000led */ +#define SATURN_PCFG_RLA 0x00000010 /* 1 = phy duplexled */ +#define SATURN_PCFG_PDS 0x00000020 /* phy debug mode. + 0 = normal */ +#define SATURN_PCFG_MTP 0x00000080 /* test point select */ +#define SATURN_PCFG_GMO 0x00000100 /* GMII observe. 1 = + GMII on SERDES pins for + monitoring. */ +#define SATURN_PCFG_FSI 0x00000200 /* 1 = freeze serdes/gmii. all + pins configed as outputs. + for power saving when using + internal phy. */ +#define SATURN_PCFG_LAD 0x00000800 /* 0 = mac core led ctrl + polarity from strapping + value. + 1 = mac core led ctrl + polarity active low. */ + + +/** transmit dma registers **/ +#define MAX_TX_RINGS_SHIFT 2 +#define MAX_TX_RINGS (1 << MAX_TX_RINGS_SHIFT) +#define MAX_TX_RINGS_MASK (MAX_TX_RINGS - 1) + +/* TX configuration. + * descr ring sizes size = 32 * (1 << n), n < 9. e.g., 0x8 = 8k. default: 0x8 + * DEFAULT: 0x3F000001 + */ +#define REG_TX_CFG 0x2004 /* TX config */ +#define TX_CFG_DMA_EN 0x00000001 /* enable TX DMA. if cleared, DMA + will stop after xfer of current + buffer has been completed. */ +#define TX_CFG_FIFO_PIO_SEL 0x00000002 /* TX DMA FIFO can be + accessed w/ FIFO addr + and data registers. + TX DMA should be + disabled. */ +#define TX_CFG_DESC_RING0_MASK 0x0000003C /* # desc entries in + ring 1. */ +#define TX_CFG_DESC_RING0_SHIFT 2 +#define TX_CFG_DESC_RINGN_MASK(a) (TX_CFG_DESC_RING0_MASK << (a)*4) +#define TX_CFG_DESC_RINGN_SHIFT(a) (TX_CFG_DESC_RING0_SHIFT + (a)*4) +#define TX_CFG_PACED_MODE 0x00100000 /* TX_ALL only set after + TX FIFO becomes empty. + if 0, TX_ALL set + if descr queue empty. */ +#define TX_CFG_DMA_RDPIPE_DIS 0x01000000 /* always set to 1 */ +#define TX_CFG_COMPWB_Q1 0x02000000 /* completion writeback happens at + the end of every packet kicked + through Q1. */ +#define TX_CFG_COMPWB_Q2 0x04000000 /* completion writeback happens at + the end of every packet kicked + through Q2. */ +#define TX_CFG_COMPWB_Q3 0x08000000 /* completion writeback happens at + the end of every packet kicked + through Q3 */ +#define TX_CFG_COMPWB_Q4 0x10000000 /* completion writeback happens at + the end of every packet kicked + through Q4 */ +#define TX_CFG_INTR_COMPWB_DIS 0x20000000 /* disable pre-interrupt completion + writeback */ +#define TX_CFG_CTX_SEL_MASK 0xC0000000 /* selects tx test port + connection + 0b00: tx mac req, + tx mac retry req, + tx ack and tx tag. + 0b01: txdma rd req, + txdma rd ack, + txdma rd rdy, + txdma rd type0 + 0b11: txdma wr req, + txdma wr ack, + txdma wr rdy, + txdma wr xfr done. */ +#define TX_CFG_CTX_SEL_SHIFT 30 + +/* 11-bit counters that point to next location in FIFO to be loaded/retrieved. + * used for diagnostics only. + */ +#define REG_TX_FIFO_WRITE_PTR 0x2014 /* TX FIFO write pointer */ +#define REG_TX_FIFO_SHADOW_WRITE_PTR 0x2018 /* TX FIFO shadow write + pointer. temp hold reg. + diagnostics only. */ +#define REG_TX_FIFO_READ_PTR 0x201C /* TX FIFO read pointer */ +#define REG_TX_FIFO_SHADOW_READ_PTR 0x2020 /* TX FIFO shadow read + pointer */ + +/* (ro) 11-bit up/down counter w/ # of frames currently in TX FIFO */ +#define REG_TX_FIFO_PKT_CNT 0x2024 /* TX FIFO packet counter */ + +/* current state of all state machines in TX */ +#define REG_TX_SM_1 0x2028 /* TX state machine reg #1 */ +#define TX_SM_1_CHAIN_MASK 0x000003FF /* chaining state machine */ +#define TX_SM_1_CSUM_MASK 0x00000C00 /* checksum state machine */ +#define TX_SM_1_FIFO_LOAD_MASK 0x0003F000 /* FIFO load state machine. + = 0x01 when TX disabled. */ +#define TX_SM_1_FIFO_UNLOAD_MASK 0x003C0000 /* FIFO unload state machine */ +#define TX_SM_1_CACHE_MASK 0x03C00000 /* desc. prefetch cache controller + state machine */ +#define TX_SM_1_CBQ_ARB_MASK 0xF8000000 /* CBQ arbiter state machine */ + +#define REG_TX_SM_2 0x202C /* TX state machine reg #2 */ +#define TX_SM_2_COMP_WB_MASK 0x07 /* completion writeback sm */ +#define TX_SM_2_SUB_LOAD_MASK 0x38 /* sub load state machine */ +#define TX_SM_2_KICK_MASK 0xC0 /* kick state machine */ + +/* 64-bit pointer to the transmit data buffer. only the 50 LSB are incremented + * while the upper 23 bits are taken from the TX descriptor + */ +#define REG_TX_DATA_PTR_LOW 0x2030 /* TX data pointer low */ +#define REG_TX_DATA_PTR_HI 0x2034 /* TX data pointer high */ + +/* 13 bit registers written by driver w/ descriptor value that follows + * last valid xmit descriptor. kick # and complete # values are used by + * the xmit dma engine to control tx descr fetching. if > 1 valid + * tx descr is available within the cache line being read, cassini will + * internally cache up to 4 of them. 0 on reset. _KICK = rw, _COMP = ro. + */ +#define REG_TX_KICK0 0x2038 /* TX kick reg #1 */ +#define REG_TX_KICKN(x) (REG_TX_KICK0 + (x)*4) +#define REG_TX_COMP0 0x2048 /* TX completion reg #1 */ +#define REG_TX_COMPN(x) (REG_TX_COMP0 + (x)*4) + +/* values of TX_COMPLETE_1-4 are written. each completion register + * is 2bytes in size and contiguous. 8B allocation w/ 8B alignment. + * NOTE: completion reg values are only written back prior to TX_INTME and + * TX_ALL interrupts. at all other times, the most up-to-date index values + * should be obtained from the REG_TX_COMPLETE_# registers. + * here's the layout: + * offset from base addr completion # byte + * 0 TX_COMPLETE_1_MSB + * 1 TX_COMPLETE_1_LSB + * 2 TX_COMPLETE_2_MSB + * 3 TX_COMPLETE_2_LSB + * 4 TX_COMPLETE_3_MSB + * 5 TX_COMPLETE_3_LSB + * 6 TX_COMPLETE_4_MSB + * 7 TX_COMPLETE_4_LSB + */ +#define TX_COMPWB_SIZE 8 +#define REG_TX_COMPWB_DB_LOW 0x2058 /* TX completion write back + base low */ +#define REG_TX_COMPWB_DB_HI 0x205C /* TX completion write back + base high */ +#define TX_COMPWB_MSB_MASK 0x00000000000000FFULL +#define TX_COMPWB_MSB_SHIFT 0 +#define TX_COMPWB_LSB_MASK 0x000000000000FF00ULL +#define TX_COMPWB_LSB_SHIFT 8 +#define TX_COMPWB_NEXT(x) ((x) >> 16) + +/* 53 MSB used as base address. 11 LSB assumed to be 0. TX desc pointer must + * be 2KB-aligned. */ +#define REG_TX_DB0_LOW 0x2060 /* TX descriptor base low #1 */ +#define REG_TX_DB0_HI 0x2064 /* TX descriptor base hi #1 */ +#define REG_TX_DBN_LOW(x) (REG_TX_DB0_LOW + (x)*8) +#define REG_TX_DBN_HI(x) (REG_TX_DB0_HI + (x)*8) + +/* 16-bit registers hold weights for the weighted round-robin of the + * four CBQ TX descr rings. weights correspond to # bytes xferred from + * host to TXFIFO in a round of WRR arbitration. can be set + * dynamically with new weights set upon completion of the current + * packet transfer from host memory to TXFIFO. a dummy write to any of + * these registers causes a queue1 pre-emption with all historical bw + * deficit data reset to 0 (useful when congestion requires a + * pre-emption/re-allocation of network bandwidth + */ +#define REG_TX_MAXBURST_0 0x2080 /* TX MaxBurst #1 */ +#define REG_TX_MAXBURST_1 0x2084 /* TX MaxBurst #2 */ +#define REG_TX_MAXBURST_2 0x2088 /* TX MaxBurst #3 */ +#define REG_TX_MAXBURST_3 0x208C /* TX MaxBurst #4 */ + +/* diagnostics access to any TX FIFO location. every access is 65 + * bits. _DATA_LOW = 32 LSB, _DATA_HI_T1/T0 = 32 MSB. _TAG = tag bit. + * writing _DATA_HI_T0 sets tag bit low, writing _DATA_HI_T1 sets tag + * bit high. TX_FIFO_PIO_SEL must be set for TX FIFO PIO access. if + * TX FIFO data integrity is desired, TX DMA should be + * disabled. _DATA_HI_Tx should be the last access of the sequence. + */ +#define REG_TX_FIFO_ADDR 0x2104 /* TX FIFO address */ +#define REG_TX_FIFO_TAG 0x2108 /* TX FIFO tag */ +#define REG_TX_FIFO_DATA_LOW 0x210C /* TX FIFO data low */ +#define REG_TX_FIFO_DATA_HI_T1 0x2110 /* TX FIFO data high t1 */ +#define REG_TX_FIFO_DATA_HI_T0 0x2114 /* TX FIFO data high t0 */ +#define REG_TX_FIFO_SIZE 0x2118 /* (ro) TX FIFO size = 0x090 = 9KB */ + +/* 9-bit register controls BIST of TX FIFO. bit set indicates that the BIST + * passed for the specified memory + */ +#define REG_TX_RAMBIST 0x211C /* TX RAMBIST control/status */ +#define TX_RAMBIST_STATE 0x01C0 /* progress state of RAMBIST + controller state machine */ +#define TX_RAMBIST_RAM33A_PASS 0x0020 /* RAM33A passed */ +#define TX_RAMBIST_RAM32A_PASS 0x0010 /* RAM32A passed */ +#define TX_RAMBIST_RAM33B_PASS 0x0008 /* RAM33B passed */ +#define TX_RAMBIST_RAM32B_PASS 0x0004 /* RAM32B passed */ +#define TX_RAMBIST_SUMMARY 0x0002 /* all RAM passed */ +#define TX_RAMBIST_START 0x0001 /* write 1 to start BIST. self + clears on completion. */ + +/** receive dma registers **/ +#define MAX_RX_DESC_RINGS 2 +#define MAX_RX_COMP_RINGS 4 + +/* receive DMA channel configuration. default: 0x80910 + * free ring size = (1 << n)*32 -> [32 - 8k] + * completion ring size = (1 << n)*128 -> [128 - 32k], n < 9 + * DEFAULT: 0x80910 + */ +#define REG_RX_CFG 0x4000 /* RX config */ +#define RX_CFG_DMA_EN 0x00000001 /* enable RX DMA. 0 stops + channel as soon as current + frame xfer has completed. + driver should disable MAC + for 200ms before disabling + RX */ +#define RX_CFG_DESC_RING_MASK 0x0000001E /* # desc entries in RX + free desc ring. + def: 0x8 = 8k */ +#define RX_CFG_DESC_RING_SHIFT 1 +#define RX_CFG_COMP_RING_MASK 0x000001E0 /* # desc entries in RX complete + ring. def: 0x8 = 32k */ +#define RX_CFG_COMP_RING_SHIFT 5 +#define RX_CFG_BATCH_DIS 0x00000200 /* disable receive desc + batching. def: 0x0 = + enabled */ +#define RX_CFG_SWIVEL_MASK 0x00001C00 /* byte offset of the 1st + data byte of the packet + w/in 8 byte boundares. + this swivels the data + DMA'ed to header + buffers, jumbo buffers + when header split is not + requested and MTU sized + buffers. def: 0x2 */ +#define RX_CFG_SWIVEL_SHIFT 10 + +/* cassini+ only */ +#define RX_CFG_DESC_RING1_MASK 0x000F0000 /* # of desc entries in + RX free desc ring 2. + def: 0x8 = 8k */ +#define RX_CFG_DESC_RING1_SHIFT 16 + + +/* the page size register allows cassini chips to do the following with + * received data: + * [--------------------------------------------------------------] page + * [off][buf1][pad][off][buf2][pad][off][buf3][pad][off][buf4][pad] + * |--------------| = PAGE_SIZE_BUFFER_STRIDE + * page = PAGE_SIZE + * offset = PAGE_SIZE_MTU_OFF + * for the above example, MTU_BUFFER_COUNT = 4. + * NOTE: as is apparent, you need to ensure that the following holds: + * MTU_BUFFER_COUNT <= PAGE_SIZE/PAGE_SIZE_BUFFER_STRIDE + * DEFAULT: 0x48002002 (8k pages) + */ +#define REG_RX_PAGE_SIZE 0x4004 /* RX page size */ +#define RX_PAGE_SIZE_MASK 0x00000003 /* size of pages pointed to + by receive descriptors. + if jumbo buffers are + supported the page size + should not be < 8k. + 0b00 = 2k, 0b01 = 4k + 0b10 = 8k, 0b11 = 16k + DEFAULT: 8k */ +#define RX_PAGE_SIZE_SHIFT 0 +#define RX_PAGE_SIZE_MTU_COUNT_MASK 0x00007800 /* # of MTU buffers the hw + packs into a page. + DEFAULT: 4 */ +#define RX_PAGE_SIZE_MTU_COUNT_SHIFT 11 +#define RX_PAGE_SIZE_MTU_STRIDE_MASK 0x18000000 /* # of bytes that separate + each MTU buffer + + offset from each + other. + 0b00 = 1k, 0b01 = 2k + 0b10 = 4k, 0b11 = 8k + DEFAULT: 0x1 */ +#define RX_PAGE_SIZE_MTU_STRIDE_SHIFT 27 +#define RX_PAGE_SIZE_MTU_OFF_MASK 0xC0000000 /* offset in each page that + hw writes the MTU buffer + into. + 0b00 = 0, + 0b01 = 64 bytes + 0b10 = 96, 0b11 = 128 + DEFAULT: 0x1 */ +#define RX_PAGE_SIZE_MTU_OFF_SHIFT 30 + +/* 11-bit counter points to next location in RX FIFO to be loaded/read. + * shadow write pointers enable retries in case of early receive aborts. + * DEFAULT: 0x0. generated on 64-bit boundaries. + */ +#define REG_RX_FIFO_WRITE_PTR 0x4008 /* RX FIFO write pointer */ +#define REG_RX_FIFO_READ_PTR 0x400C /* RX FIFO read pointer */ +#define REG_RX_IPP_FIFO_SHADOW_WRITE_PTR 0x4010 /* RX IPP FIFO shadow write + pointer */ +#define REG_RX_IPP_FIFO_SHADOW_READ_PTR 0x4014 /* RX IPP FIFO shadow read + pointer */ +#define REG_RX_IPP_FIFO_READ_PTR 0x400C /* RX IPP FIFO read + pointer. (8-bit counter) */ + +/* current state of RX DMA state engines + other info + * DEFAULT: 0x0 + */ +#define REG_RX_DEBUG 0x401C /* RX debug */ +#define RX_DEBUG_LOAD_STATE_MASK 0x0000000F /* load state machine w/ MAC: + 0x0 = idle, 0x1 = load_bop + 0x2 = load 1, 0x3 = load 2 + 0x4 = load 3, 0x5 = load 4 + 0x6 = last detect + 0x7 = wait req + 0x8 = wait req statuss 1st + 0x9 = load st + 0xa = bubble mac + 0xb = error */ +#define RX_DEBUG_LM_STATE_MASK 0x00000070 /* load state machine w/ HP and + RX FIFO: + 0x0 = idle, 0x1 = hp xfr + 0x2 = wait hp ready + 0x3 = wait flow code + 0x4 = fifo xfer + 0x5 = make status + 0x6 = csum ready + 0x7 = error */ +#define RX_DEBUG_FC_STATE_MASK 0x000000180 /* flow control state machine + w/ MAC: + 0x0 = idle + 0x1 = wait xoff ack + 0x2 = wait xon + 0x3 = wait xon ack */ +#define RX_DEBUG_DATA_STATE_MASK 0x000001E00 /* unload data state machine + states: + 0x0 = idle data + 0x1 = header begin + 0x2 = xfer header + 0x3 = xfer header ld + 0x4 = mtu begin + 0x5 = xfer mtu + 0x6 = xfer mtu ld + 0x7 = jumbo begin + 0x8 = xfer jumbo + 0x9 = xfer jumbo ld + 0xa = reas begin + 0xb = xfer reas + 0xc = flush tag + 0xd = xfer reas ld + 0xe = error + 0xf = bubble idle */ +#define RX_DEBUG_DESC_STATE_MASK 0x0001E000 /* unload desc state machine + states: + 0x0 = idle desc + 0x1 = wait ack + 0x9 = wait ack 2 + 0x2 = fetch desc 1 + 0xa = fetch desc 2 + 0x3 = load ptrs + 0x4 = wait dma + 0x5 = wait ack batch + 0x6 = post batch + 0x7 = xfr done */ +#define RX_DEBUG_INTR_READ_PTR_MASK 0x30000000 /* interrupt read ptr of the + interrupt queue */ +#define RX_DEBUG_INTR_WRITE_PTR_MASK 0xC0000000 /* interrupt write pointer + of the interrupt queue */ + +/* flow control frames are emmitted using two PAUSE thresholds: + * XOFF PAUSE uses pause time value pre-programmed in the Send PAUSE MAC reg + * XON PAUSE uses a pause time of 0. granularity of threshold is 64bytes. + * PAUSE thresholds defined in terms of FIFO occupancy and may be translated + * into FIFO vacancy using RX_FIFO_SIZE. setting ON will trigger XON frames + * when FIFO reaches 0. OFF threshold should not be > size of RX FIFO. max + * value is is 0x6F. + * DEFAULT: 0x00078 + */ +#define REG_RX_PAUSE_THRESH 0x4020 /* RX pause thresholds */ +#define RX_PAUSE_THRESH_QUANTUM 64 +#define RX_PAUSE_THRESH_OFF_MASK 0x000001FF /* XOFF PAUSE emitted when + RX FIFO occupancy > + value*64B */ +#define RX_PAUSE_THRESH_OFF_SHIFT 0 +#define RX_PAUSE_THRESH_ON_MASK 0x001FF000 /* XON PAUSE emitted after + emitting XOFF PAUSE when RX + FIFO occupancy falls below + this value*64B. must be + < XOFF threshold. if = + RX_FIFO_SIZE< XON frames are + never emitted. */ +#define RX_PAUSE_THRESH_ON_SHIFT 12 + +/* 13-bit register used to control RX desc fetching and intr generation. if 4+ + * valid RX descriptors are available, Cassini will read 4 at a time. + * writing N means that all desc up to *but* excluding N are available. N must + * be a multiple of 4 (N % 4 = 0). first desc should be cache-line aligned. + * DEFAULT: 0 on reset + */ +#define REG_RX_KICK 0x4024 /* RX kick reg */ + +/* 8KB aligned 64-bit pointer to the base of the RX free/completion rings. + * lower 13 bits of the low register are hard-wired to 0. + */ +#define REG_RX_DB_LOW 0x4028 /* RX descriptor ring + base low */ +#define REG_RX_DB_HI 0x402C /* RX descriptor ring + base hi */ +#define REG_RX_CB_LOW 0x4030 /* RX completion ring + base low */ +#define REG_RX_CB_HI 0x4034 /* RX completion ring + base hi */ +/* 13-bit register indicate desc used by cassini for receive frames. used + * for diagnostic purposes. + * DEFAULT: 0 on reset + */ +#define REG_RX_COMP 0x4038 /* (ro) RX completion */ + +/* HEAD and TAIL are used to control RX desc posting and interrupt + * generation. hw moves the head register to pass ownership to sw. sw + * moves the tail register to pass ownership back to hw. to give all + * entries to hw, set TAIL = HEAD. if HEAD and TAIL indicate that no + * more entries are available, DMA will pause and an interrupt will be + * generated to indicate no more entries are available. sw can use + * this interrupt to reduce the # of times it must update the + * completion tail register. + * DEFAULT: 0 on reset + */ +#define REG_RX_COMP_HEAD 0x403C /* RX completion head */ +#define REG_RX_COMP_TAIL 0x4040 /* RX completion tail */ + +/* values used for receive interrupt blanking. loaded each time the ISR is read + * DEFAULT: 0x00000000 + */ +#define REG_RX_BLANK 0x4044 /* RX blanking register + for ISR read */ +#define RX_BLANK_INTR_PKT_MASK 0x000001FF /* RX_DONE intr asserted if + this many sets of completion + writebacks (up to 2 packets) + occur since the last time + the ISR was read. 0 = no + packet blanking */ +#define RX_BLANK_INTR_PKT_SHIFT 0 +#define RX_BLANK_INTR_TIME_MASK 0x3FFFF000 /* RX_DONE interrupt asserted + if that many clocks were + counted since last time the + ISR was read. + each count is 512 core + clocks (125MHz). 0 = no + time blanking */ +#define RX_BLANK_INTR_TIME_SHIFT 12 + +/* values used for interrupt generation based on threshold values of how + * many free desc and completion entries are available for hw use. + * DEFAULT: 0x00000000 + */ +#define REG_RX_AE_THRESH 0x4048 /* RX almost empty + thresholds */ +#define RX_AE_THRESH_FREE_MASK 0x00001FFF /* RX_BUF_AE will be + generated if # desc + avail for hw use <= + # */ +#define RX_AE_THRESH_FREE_SHIFT 0 +#define RX_AE_THRESH_COMP_MASK 0x0FFFE000 /* RX_COMP_AE will be + generated if # of + completion entries + avail for hw use <= + # */ +#define RX_AE_THRESH_COMP_SHIFT 13 + +/* probabilities for random early drop (RED) thresholds on a FIFO threshold + * basis. probability should increase when the FIFO level increases. control + * packets are never dropped and not counted in stats. probability programmed + * on a 12.5% granularity. e.g., 0x1 = 1/8 packets dropped. + * DEFAULT: 0x00000000 + */ +#define REG_RX_RED 0x404C /* RX random early detect enable */ +#define RX_RED_4K_6K_FIFO_MASK 0x000000FF /* 4KB < FIFO thresh < 6KB */ +#define RX_RED_6K_8K_FIFO_MASK 0x0000FF00 /* 6KB < FIFO thresh < 8KB */ +#define RX_RED_8K_10K_FIFO_MASK 0x00FF0000 /* 8KB < FIFO thresh < 10KB */ +#define RX_RED_10K_12K_FIFO_MASK 0xFF000000 /* 10KB < FIFO thresh < 12KB */ + +/* FIFO fullness levels for RX FIFO, RX control FIFO, and RX IPP FIFO. + * RX control FIFO = # of packets in RX FIFO. + * DEFAULT: 0x0 + */ +#define REG_RX_FIFO_FULLNESS 0x4050 /* (ro) RX FIFO fullness */ +#define RX_FIFO_FULLNESS_RX_FIFO_MASK 0x3FF80000 /* level w/ 8B granularity */ +#define RX_FIFO_FULLNESS_IPP_FIFO_MASK 0x0007FF00 /* level w/ 8B granularity */ +#define RX_FIFO_FULLNESS_RX_PKT_MASK 0x000000FF /* # packets in RX FIFO */ +#define REG_RX_IPP_PACKET_COUNT 0x4054 /* RX IPP packet counter */ +#define REG_RX_WORK_DMA_PTR_LOW 0x4058 /* RX working DMA ptr low */ +#define REG_RX_WORK_DMA_PTR_HI 0x405C /* RX working DMA ptr + high */ + +/* BIST testing ro RX FIFO, RX control FIFO, and RX IPP FIFO. only RX BIST + * START/COMPLETE is writeable. START will clear when the BIST has completed + * checking all 17 RAMS. + * DEFAULT: 0bxxxx xxxxx xxxx xxxx xxxx x000 0000 0000 00x0 + */ +#define REG_RX_BIST 0x4060 /* (ro) RX BIST */ +#define RX_BIST_32A_PASS 0x80000000 /* RX FIFO 32A passed */ +#define RX_BIST_33A_PASS 0x40000000 /* RX FIFO 33A passed */ +#define RX_BIST_32B_PASS 0x20000000 /* RX FIFO 32B passed */ +#define RX_BIST_33B_PASS 0x10000000 /* RX FIFO 33B passed */ +#define RX_BIST_32C_PASS 0x08000000 /* RX FIFO 32C passed */ +#define RX_BIST_33C_PASS 0x04000000 /* RX FIFO 33C passed */ +#define RX_BIST_IPP_32A_PASS 0x02000000 /* RX IPP FIFO 33B passed */ +#define RX_BIST_IPP_33A_PASS 0x01000000 /* RX IPP FIFO 33A passed */ +#define RX_BIST_IPP_32B_PASS 0x00800000 /* RX IPP FIFO 32B passed */ +#define RX_BIST_IPP_33B_PASS 0x00400000 /* RX IPP FIFO 33B passed */ +#define RX_BIST_IPP_32C_PASS 0x00200000 /* RX IPP FIFO 32C passed */ +#define RX_BIST_IPP_33C_PASS 0x00100000 /* RX IPP FIFO 33C passed */ +#define RX_BIST_CTRL_32_PASS 0x00800000 /* RX CTRL FIFO 32 passed */ +#define RX_BIST_CTRL_33_PASS 0x00400000 /* RX CTRL FIFO 33 passed */ +#define RX_BIST_REAS_26A_PASS 0x00200000 /* RX Reas 26A passed */ +#define RX_BIST_REAS_26B_PASS 0x00100000 /* RX Reas 26B passed */ +#define RX_BIST_REAS_27_PASS 0x00080000 /* RX Reas 27 passed */ +#define RX_BIST_STATE_MASK 0x00078000 /* BIST state machine */ +#define RX_BIST_SUMMARY 0x00000002 /* when BIST complete, + summary pass bit + contains AND of BIST + results of all 16 + RAMS */ +#define RX_BIST_START 0x00000001 /* write 1 to start + BIST. self clears + on completion. */ + +/* next location in RX CTRL FIFO that will be loaded w/ data from RX IPP/read + * from to retrieve packet control info. + * DEFAULT: 0 + */ +#define REG_RX_CTRL_FIFO_WRITE_PTR 0x4064 /* (ro) RX control FIFO + write ptr */ +#define REG_RX_CTRL_FIFO_READ_PTR 0x4068 /* (ro) RX control FIFO read + ptr */ + +/* receive interrupt blanking. loaded each time interrupt alias register is + * read. + * DEFAULT: 0x0 + */ +#define REG_RX_BLANK_ALIAS_READ 0x406C /* RX blanking register for + alias read */ +#define RX_BAR_INTR_PACKET_MASK 0x000001FF /* assert RX_DONE if # + completion writebacks + > # since last ISR + read. 0 = no + blanking. up to 2 + packets per + completion wb. */ +#define RX_BAR_INTR_TIME_MASK 0x3FFFF000 /* assert RX_DONE if # + clocks > # since last + ISR read. each count + is 512 core clocks + (125MHz). 0 = no + blanking. */ + +/* diagnostic access to RX FIFO. 32 LSB accessed via DATA_LOW. 32 MSB accessed + * via DATA_HI_T0 or DATA_HI_T1. TAG reads the tag bit. writing HI_T0 + * will unset the tag bit while writing HI_T1 will set the tag bit. to reset + * to normal operation after diagnostics, write to address location 0x0. + * RX_DMA_EN bit must be set to 0x0 for RX FIFO PIO access. DATA_HI should + * be the last write access of a write sequence. + * DEFAULT: undefined + */ +#define REG_RX_FIFO_ADDR 0x4080 /* RX FIFO address */ +#define REG_RX_FIFO_TAG 0x4084 /* RX FIFO tag */ +#define REG_RX_FIFO_DATA_LOW 0x4088 /* RX FIFO data low */ +#define REG_RX_FIFO_DATA_HI_T0 0x408C /* RX FIFO data high T0 */ +#define REG_RX_FIFO_DATA_HI_T1 0x4090 /* RX FIFO data high T1 */ + +/* diagnostic assess to RX CTRL FIFO. 8-bit FIFO_ADDR holds address of + * 81 bit control entry and 6 bit flow id. LOW and MID are both 32-bit + * accesses. HI is 7-bits with 6-bit flow id and 1 bit control + * word. RX_DMA_EN must be 0 for RX CTRL FIFO PIO access. DATA_HI + * should be last write access of the write sequence. + * DEFAULT: undefined + */ +#define REG_RX_CTRL_FIFO_ADDR 0x4094 /* RX Control FIFO and + Batching FIFO addr */ +#define REG_RX_CTRL_FIFO_DATA_LOW 0x4098 /* RX Control FIFO data + low */ +#define REG_RX_CTRL_FIFO_DATA_MID 0x409C /* RX Control FIFO data + mid */ +#define REG_RX_CTRL_FIFO_DATA_HI 0x4100 /* RX Control FIFO data + hi and flow id */ +#define RX_CTRL_FIFO_DATA_HI_CTRL 0x0001 /* upper bit of ctrl word */ +#define RX_CTRL_FIFO_DATA_HI_FLOW_MASK 0x007E /* flow id */ + +/* diagnostic access to RX IPP FIFO. same semantics as RX_FIFO. + * DEFAULT: undefined + */ +#define REG_RX_IPP_FIFO_ADDR 0x4104 /* RX IPP FIFO address */ +#define REG_RX_IPP_FIFO_TAG 0x4108 /* RX IPP FIFO tag */ +#define REG_RX_IPP_FIFO_DATA_LOW 0x410C /* RX IPP FIFO data low */ +#define REG_RX_IPP_FIFO_DATA_HI_T0 0x4110 /* RX IPP FIFO data high + T0 */ +#define REG_RX_IPP_FIFO_DATA_HI_T1 0x4114 /* RX IPP FIFO data high + T1 */ + +/* 64-bit pointer to receive data buffer in host memory used for headers and + * small packets. MSB in high register. loaded by DMA state machine and + * increments as DMA writes receive data. only 50 LSB are incremented. top + * 13 bits taken from RX descriptor. + * DEFAULT: undefined + */ +#define REG_RX_HEADER_PAGE_PTR_LOW 0x4118 /* (ro) RX header page ptr + low */ +#define REG_RX_HEADER_PAGE_PTR_HI 0x411C /* (ro) RX header page ptr + high */ +#define REG_RX_MTU_PAGE_PTR_LOW 0x4120 /* (ro) RX MTU page pointer + low */ +#define REG_RX_MTU_PAGE_PTR_HI 0x4124 /* (ro) RX MTU page pointer + high */ + +/* PIO diagnostic access to RX reassembly DMA Table RAM. 6-bit register holds + * one of 64 79-bit locations in the RX Reassembly DMA table and the addr of + * one of the 64 byte locations in the Batching table. LOW holds 32 LSB. + * MID holds the next 32 LSB. HIGH holds the 15 MSB. RX_DMA_EN must be set + * to 0 for PIO access. DATA_HIGH should be last write of write sequence. + * layout: + * reassmbl ptr [78:15] | reassmbl index [14:1] | reassmbl entry valid [0] + * DEFAULT: undefined + */ +#define REG_RX_TABLE_ADDR 0x4128 /* RX reassembly DMA table + address */ +#define RX_TABLE_ADDR_MASK 0x0000003F /* address mask */ + +#define REG_RX_TABLE_DATA_LOW 0x412C /* RX reassembly DMA table + data low */ +#define REG_RX_TABLE_DATA_MID 0x4130 /* RX reassembly DMA table + data mid */ +#define REG_RX_TABLE_DATA_HI 0x4134 /* RX reassembly DMA table + data high */ + +/* cassini+ only */ +/* 8KB aligned 64-bit pointer to base of RX rings. lower 13 bits hardwired to + * 0. same semantics as primary desc/complete rings. + */ +#define REG_PLUS_RX_DB1_LOW 0x4200 /* RX descriptor ring + 2 base low */ +#define REG_PLUS_RX_DB1_HI 0x4204 /* RX descriptor ring + 2 base high */ +#define REG_PLUS_RX_CB1_LOW 0x4208 /* RX completion ring + 2 base low. 4 total */ +#define REG_PLUS_RX_CB1_HI 0x420C /* RX completion ring + 2 base high. 4 total */ +#define REG_PLUS_RX_CBN_LOW(x) (REG_PLUS_RX_CB1_LOW + 8*((x) - 1)) +#define REG_PLUS_RX_CBN_HI(x) (REG_PLUS_RX_CB1_HI + 8*((x) - 1)) +#define REG_PLUS_RX_KICK1 0x4220 /* RX Kick 2 register */ +#define REG_PLUS_RX_COMP1 0x4224 /* (ro) RX completion 2 + reg */ +#define REG_PLUS_RX_COMP1_HEAD 0x4228 /* (ro) RX completion 2 + head reg. 4 total. */ +#define REG_PLUS_RX_COMP1_TAIL 0x422C /* RX completion 2 + tail reg. 4 total. */ +#define REG_PLUS_RX_COMPN_HEAD(x) (REG_PLUS_RX_COMP1_HEAD + 8*((x) - 1)) +#define REG_PLUS_RX_COMPN_TAIL(x) (REG_PLUS_RX_COMP1_TAIL + 8*((x) - 1)) +#define REG_PLUS_RX_AE1_THRESH 0x4240 /* RX almost empty 2 + thresholds */ +#define RX_AE1_THRESH_FREE_MASK RX_AE_THRESH_FREE_MASK +#define RX_AE1_THRESH_FREE_SHIFT RX_AE_THRESH_FREE_SHIFT + +/** header parser registers **/ + +/* RX parser configuration register. + * DEFAULT: 0x1651004 + */ +#define REG_HP_CFG 0x4140 /* header parser + configuration reg */ +#define HP_CFG_PARSE_EN 0x00000001 /* enab header parsing */ +#define HP_CFG_NUM_CPU_MASK 0x000000FC /* # processors + 0 = 64. 0x3f = 63 */ +#define HP_CFG_NUM_CPU_SHIFT 2 +#define HP_CFG_SYN_INC_MASK 0x00000100 /* SYN bit won't increment + TCP seq # by one when + stored in FDBM */ +#define HP_CFG_TCP_THRESH_MASK 0x000FFE00 /* # bytes of TCP data + needed to be considered + for reassembly */ +#define HP_CFG_TCP_THRESH_SHIFT 9 + +/* access to RX Instruction RAM. 5-bit register/counter holds addr + * of 39 bit entry to be read/written. 32 LSB in _DATA_LOW. 7 MSB in _DATA_HI. + * RX_DMA_EN must be 0 for RX instr PIO access. DATA_HI should be last access + * of sequence. + * DEFAULT: undefined + */ +#define REG_HP_INSTR_RAM_ADDR 0x4144 /* HP instruction RAM + address */ +#define HP_INSTR_RAM_ADDR_MASK 0x01F /* 5-bit mask */ +#define REG_HP_INSTR_RAM_DATA_LOW 0x4148 /* HP instruction RAM + data low */ +#define HP_INSTR_RAM_LOW_OUTMASK_MASK 0x0000FFFF +#define HP_INSTR_RAM_LOW_OUTMASK_SHIFT 0 +#define HP_INSTR_RAM_LOW_OUTSHIFT_MASK 0x000F0000 +#define HP_INSTR_RAM_LOW_OUTSHIFT_SHIFT 16 +#define HP_INSTR_RAM_LOW_OUTEN_MASK 0x00300000 +#define HP_INSTR_RAM_LOW_OUTEN_SHIFT 20 +#define HP_INSTR_RAM_LOW_OUTARG_MASK 0xFFC00000 +#define HP_INSTR_RAM_LOW_OUTARG_SHIFT 22 +#define REG_HP_INSTR_RAM_DATA_MID 0x414C /* HP instruction RAM + data mid */ +#define HP_INSTR_RAM_MID_OUTARG_MASK 0x00000003 +#define HP_INSTR_RAM_MID_OUTARG_SHIFT 0 +#define HP_INSTR_RAM_MID_OUTOP_MASK 0x0000003C +#define HP_INSTR_RAM_MID_OUTOP_SHIFT 2 +#define HP_INSTR_RAM_MID_FNEXT_MASK 0x000007C0 +#define HP_INSTR_RAM_MID_FNEXT_SHIFT 6 +#define HP_INSTR_RAM_MID_FOFF_MASK 0x0003F800 +#define HP_INSTR_RAM_MID_FOFF_SHIFT 11 +#define HP_INSTR_RAM_MID_SNEXT_MASK 0x007C0000 +#define HP_INSTR_RAM_MID_SNEXT_SHIFT 18 +#define HP_INSTR_RAM_MID_SOFF_MASK 0x3F800000 +#define HP_INSTR_RAM_MID_SOFF_SHIFT 23 +#define HP_INSTR_RAM_MID_OP_MASK 0xC0000000 +#define HP_INSTR_RAM_MID_OP_SHIFT 30 +#define REG_HP_INSTR_RAM_DATA_HI 0x4150 /* HP instruction RAM + data high */ +#define HP_INSTR_RAM_HI_VAL_MASK 0x0000FFFF +#define HP_INSTR_RAM_HI_VAL_SHIFT 0 +#define HP_INSTR_RAM_HI_MASK_MASK 0xFFFF0000 +#define HP_INSTR_RAM_HI_MASK_SHIFT 16 + +/* PIO access into RX Header parser data RAM and flow database. + * 11-bit register. Data fills the LSB portion of bus if less than 32 bits. + * DATA_RAM: write RAM_FDB_DATA with index to access DATA_RAM. + * RAM bytes = 4*(x - 1) + [3:0]. e.g., 0 -> [3:0], 31 -> [123:120] + * FLOWDB: write DATA_RAM_FDB register and then read/write FDB1-12 to access + * flow database. + * RX_DMA_EN must be 0 for RX parser RAM PIO access. RX Parser RAM data reg + * should be the last write access of the write sequence. + * DEFAULT: undefined + */ +#define REG_HP_DATA_RAM_FDB_ADDR 0x4154 /* HP data and FDB + RAM address */ +#define HP_DATA_RAM_FDB_DATA_MASK 0x001F /* select 1 of 86 byte + locations in header + parser data ram to + read/write */ +#define HP_DATA_RAM_FDB_FDB_MASK 0x3F00 /* 1 of 64 353-bit locations + in the flow database */ +#define REG_HP_DATA_RAM_DATA 0x4158 /* HP data RAM data */ + +/* HP flow database registers: 1 - 12, 0x415C - 0x4188, 4 8-bit bytes + * FLOW_DB(1) = IP_SA[127:96], FLOW_DB(2) = IP_SA[95:64] + * FLOW_DB(3) = IP_SA[63:32], FLOW_DB(4) = IP_SA[31:0] + * FLOW_DB(5) = IP_DA[127:96], FLOW_DB(6) = IP_DA[95:64] + * FLOW_DB(7) = IP_DA[63:32], FLOW_DB(8) = IP_DA[31:0] + * FLOW_DB(9) = {TCP_SP[15:0],TCP_DP[15:0]} + * FLOW_DB(10) = bit 0 has value for flow valid + * FLOW_DB(11) = TCP_SEQ[63:32], FLOW_DB(12) = TCP_SEQ[31:0] + */ +#define REG_HP_FLOW_DB0 0x415C /* HP flow database 1 reg */ +#define REG_HP_FLOW_DBN(x) (REG_HP_FLOW_DB0 + (x)*4) + +/* diagnostics for RX Header Parser block. + * ASUN: the header parser state machine register is used for diagnostics + * purposes. however, the spec doesn't have any details on it. + */ +#define REG_HP_STATE_MACHINE 0x418C /* (ro) HP state machine */ +#define REG_HP_STATUS0 0x4190 /* (ro) HP status 1 */ +#define HP_STATUS0_SAP_MASK 0xFFFF0000 /* SAP */ +#define HP_STATUS0_L3_OFF_MASK 0x0000FE00 /* L3 offset */ +#define HP_STATUS0_LB_CPUNUM_MASK 0x000001F8 /* load balancing CPU + number */ +#define HP_STATUS0_HRP_OPCODE_MASK 0x00000007 /* HRP opcode */ + +#define REG_HP_STATUS1 0x4194 /* (ro) HP status 2 */ +#define HP_STATUS1_ACCUR2_MASK 0xE0000000 /* accu R2[6:4] */ +#define HP_STATUS1_FLOWID_MASK 0x1F800000 /* flow id */ +#define HP_STATUS1_TCP_OFF_MASK 0x007F0000 /* tcp payload offset */ +#define HP_STATUS1_TCP_SIZE_MASK 0x0000FFFF /* tcp payload size */ + +#define REG_HP_STATUS2 0x4198 /* (ro) HP status 3 */ +#define HP_STATUS2_ACCUR2_MASK 0xF0000000 /* accu R2[3:0] */ +#define HP_STATUS2_CSUM_OFF_MASK 0x07F00000 /* checksum start + start offset */ +#define HP_STATUS2_ACCUR1_MASK 0x000FE000 /* accu R1 */ +#define HP_STATUS2_FORCE_DROP 0x00001000 /* force drop */ +#define HP_STATUS2_BWO_REASSM 0x00000800 /* batching w/o + reassembly */ +#define HP_STATUS2_JH_SPLIT_EN 0x00000400 /* jumbo header split + enable */ +#define HP_STATUS2_FORCE_TCP_NOCHECK 0x00000200 /* force tcp no payload + check */ +#define HP_STATUS2_DATA_MASK_ZERO 0x00000100 /* mask of data length + equal to zero */ +#define HP_STATUS2_FORCE_TCP_CHECK 0x00000080 /* force tcp payload + chk */ +#define HP_STATUS2_MASK_TCP_THRESH 0x00000040 /* mask of payload + threshold */ +#define HP_STATUS2_NO_ASSIST 0x00000020 /* no assist */ +#define HP_STATUS2_CTRL_PACKET_FLAG 0x00000010 /* control packet flag */ +#define HP_STATUS2_TCP_FLAG_CHECK 0x00000008 /* tcp flag check */ +#define HP_STATUS2_SYN_FLAG 0x00000004 /* syn flag */ +#define HP_STATUS2_TCP_CHECK 0x00000002 /* tcp payload chk */ +#define HP_STATUS2_TCP_NOCHECK 0x00000001 /* tcp no payload chk */ + +/* BIST for header parser(HP) and flow database memories (FDBM). set _START + * to start BIST. controller clears _START on completion. _START can also + * be cleared to force termination of BIST. a bit set indicates that that + * memory passed its BIST. + */ +#define REG_HP_RAM_BIST 0x419C /* HP RAM BIST reg */ +#define HP_RAM_BIST_HP_DATA_PASS 0x80000000 /* HP data ram */ +#define HP_RAM_BIST_HP_INSTR0_PASS 0x40000000 /* HP instr ram 0 */ +#define HP_RAM_BIST_HP_INSTR1_PASS 0x20000000 /* HP instr ram 1 */ +#define HP_RAM_BIST_HP_INSTR2_PASS 0x10000000 /* HP instr ram 2 */ +#define HP_RAM_BIST_FDBM_AGE0_PASS 0x08000000 /* FDBM aging RAM0 */ +#define HP_RAM_BIST_FDBM_AGE1_PASS 0x04000000 /* FDBM aging RAM1 */ +#define HP_RAM_BIST_FDBM_FLOWID00_PASS 0x02000000 /* FDBM flowid RAM0 + bank 0 */ +#define HP_RAM_BIST_FDBM_FLOWID10_PASS 0x01000000 /* FDBM flowid RAM1 + bank 0 */ +#define HP_RAM_BIST_FDBM_FLOWID20_PASS 0x00800000 /* FDBM flowid RAM2 + bank 0 */ +#define HP_RAM_BIST_FDBM_FLOWID30_PASS 0x00400000 /* FDBM flowid RAM3 + bank 0 */ +#define HP_RAM_BIST_FDBM_FLOWID01_PASS 0x00200000 /* FDBM flowid RAM0 + bank 1 */ +#define HP_RAM_BIST_FDBM_FLOWID11_PASS 0x00100000 /* FDBM flowid RAM1 + bank 2 */ +#define HP_RAM_BIST_FDBM_FLOWID21_PASS 0x00080000 /* FDBM flowid RAM2 + bank 1 */ +#define HP_RAM_BIST_FDBM_FLOWID31_PASS 0x00040000 /* FDBM flowid RAM3 + bank 1 */ +#define HP_RAM_BIST_FDBM_TCPSEQ_PASS 0x00020000 /* FDBM tcp sequence + RAM */ +#define HP_RAM_BIST_SUMMARY 0x00000002 /* all BIST tests */ +#define HP_RAM_BIST_START 0x00000001 /* start/stop BIST */ + + +/** MAC registers. **/ +/* reset bits are set using a PIO write and self-cleared after the command + * execution has completed. + */ +#define REG_MAC_TX_RESET 0x6000 /* TX MAC software reset + command (default: 0x0) */ +#define REG_MAC_RX_RESET 0x6004 /* RX MAC software reset + command (default: 0x0) */ +/* execute a pause flow control frame transmission + DEFAULT: 0x0XXXX */ +#define REG_MAC_SEND_PAUSE 0x6008 /* send pause command reg */ +#define MAC_SEND_PAUSE_TIME_MASK 0x0000FFFF /* value of pause time + to be sent on network + in units of slot + times */ +#define MAC_SEND_PAUSE_SEND 0x00010000 /* send pause flow ctrl + frame on network */ + +/* bit set indicates that event occurred. auto-cleared when status register + * is read and have corresponding mask bits in mask register. events will + * trigger an interrupt if the corresponding mask bit is 0. + * status register default: 0x00000000 + * mask register default = 0xFFFFFFFF on reset + */ +#define REG_MAC_TX_STATUS 0x6010 /* TX MAC status reg */ +#define MAC_TX_FRAME_XMIT 0x0001 /* successful frame + transmision */ +#define MAC_TX_UNDERRUN 0x0002 /* terminated frame + transmission due to + data starvation in the + xmit data path */ +#define MAC_TX_MAX_PACKET_ERR 0x0004 /* frame exceeds max allowed + length passed to TX MAC + by the DMA engine */ +#define MAC_TX_COLL_NORMAL 0x0008 /* rollover of the normal + collision counter */ +#define MAC_TX_COLL_EXCESS 0x0010 /* rollover of the excessive + collision counter */ +#define MAC_TX_COLL_LATE 0x0020 /* rollover of the late + collision counter */ +#define MAC_TX_COLL_FIRST 0x0040 /* rollover of the first + collision counter */ +#define MAC_TX_DEFER_TIMER 0x0080 /* rollover of the defer + timer */ +#define MAC_TX_PEAK_ATTEMPTS 0x0100 /* rollover of the peak + attempts counter */ + +#define REG_MAC_RX_STATUS 0x6014 /* RX MAC status reg */ +#define MAC_RX_FRAME_RECV 0x0001 /* successful receipt of + a frame */ +#define MAC_RX_OVERFLOW 0x0002 /* dropped frame due to + RX FIFO overflow */ +#define MAC_RX_FRAME_COUNT 0x0004 /* rollover of receive frame + counter */ +#define MAC_RX_ALIGN_ERR 0x0008 /* rollover of alignment + error counter */ +#define MAC_RX_CRC_ERR 0x0010 /* rollover of crc error + counter */ +#define MAC_RX_LEN_ERR 0x0020 /* rollover of length + error counter */ +#define MAC_RX_VIOL_ERR 0x0040 /* rollover of code + violation error */ + +/* DEFAULT: 0xXXXX0000 on reset */ +#define REG_MAC_CTRL_STATUS 0x6018 /* MAC control status reg */ +#define MAC_CTRL_PAUSE_RECEIVED 0x00000001 /* successful + reception of a + pause control + frame */ +#define MAC_CTRL_PAUSE_STATE 0x00000002 /* MAC has made a + transition from + "not paused" to + "paused" */ +#define MAC_CTRL_NOPAUSE_STATE 0x00000004 /* MAC has made a + transition from + "paused" to "not + paused" */ +#define MAC_CTRL_PAUSE_TIME_MASK 0xFFFF0000 /* value of pause time + operand that was + received in the last + pause flow control + frame */ + +/* layout identical to TX MAC[8:0] */ +#define REG_MAC_TX_MASK 0x6020 /* TX MAC mask reg */ +/* layout identical to RX MAC[6:0] */ +#define REG_MAC_RX_MASK 0x6024 /* RX MAC mask reg */ +/* layout identical to CTRL MAC[2:0] */ +#define REG_MAC_CTRL_MASK 0x6028 /* MAC control mask reg */ + +/* to ensure proper operation, CFG_EN must be cleared to 0 and a delay + * imposed before writes to other bits in the TX_MAC_CFG register or any of + * the MAC parameters is performed. delay dependent upon time required to + * transmit a maximum size frame (= MAC_FRAMESIZE_MAX*8/Mbps). e.g., + * the delay for a 1518-byte frame on a 100Mbps network is 125us. + * alternatively, just poll TX_CFG_EN until it reads back as 0. + * NOTE: on half-duplex 1Gbps, TX_CFG_CARRIER_EXTEND and + * RX_CFG_CARRIER_EXTEND should be set and the SLOT_TIME register should + * be 0x200 (slot time of 512 bytes) + */ +#define REG_MAC_TX_CFG 0x6030 /* TX MAC config reg */ +#define MAC_TX_CFG_EN 0x0001 /* enable TX MAC. 0 will + force TXMAC state + machine to remain in + idle state or to + transition to idle state + on completion of an + ongoing packet. */ +#define MAC_TX_CFG_IGNORE_CARRIER 0x0002 /* disable CSMA/CD deferral + process. set to 1 when + full duplex and 0 when + half duplex */ +#define MAC_TX_CFG_IGNORE_COLL 0x0004 /* disable CSMA/CD backoff + algorithm. set to 1 when + full duplex and 0 when + half duplex */ +#define MAC_TX_CFG_IPG_EN 0x0008 /* enable extension of the + Rx-to-TX IPG. after + receiving a frame, TX + MAC will reset its + deferral process to + carrier sense for the + amount of time = IPG0 + + IPG1 and commit to + transmission for time + specified in IPG2. when + 0 or when xmitting frames + back-to-pack (Tx-to-Tx + IPG), TX MAC ignores + IPG0 and will only use + IPG1 for deferral time. + IPG2 still used. */ +#define MAC_TX_CFG_NEVER_GIVE_UP_EN 0x0010 /* TX MAC will not easily + give up on frame + xmission. if backoff + algorithm reaches the + ATTEMPT_LIMIT, it will + clear attempts counter + and continue trying to + send the frame as + specified by + GIVE_UP_LIM. when 0, + TX MAC will execute + standard CSMA/CD prot. */ +#define MAC_TX_CFG_NEVER_GIVE_UP_LIM 0x0020 /* when set, TX MAC will + continue to try to xmit + until successful. when + 0, TX MAC will continue + to try xmitting until + successful or backoff + algorithm reaches + ATTEMPT_LIMIT*16 */ +#define MAC_TX_CFG_NO_BACKOFF 0x0040 /* modify CSMA/CD to disable + backoff algorithm. TX + MAC will not back off + after a xmission attempt + that resulted in a + collision. */ +#define MAC_TX_CFG_SLOW_DOWN 0x0080 /* modify CSMA/CD so that + deferral process is reset + in response to carrier + sense during the entire + duration of IPG. TX MAC + will only commit to frame + xmission after frame + xmission has actually + begun. */ +#define MAC_TX_CFG_NO_FCS 0x0100 /* TX MAC will not generate + CRC for all xmitted + packets. when clear, CRC + generation is dependent + upon NO_CRC bit in the + xmit control word from + TX DMA */ +#define MAC_TX_CFG_CARRIER_EXTEND 0x0200 /* enables xmit part of the + carrier extension + feature. this allows for + longer collision domains + by extending the carrier + and collision window + from the end of FCS until + the end of the slot time + if necessary. Required + for half-duplex at 1Gbps, + clear otherwise. */ + +/* when CRC is not stripped, reassembly packets will not contain the CRC. + * these will be stripped by HRP because it reassembles layer 4 data, and the + * CRC is layer 2. however, non-reassembly packets will still contain the CRC + * when passed to the host. to ensure proper operation, need to wait 3.2ms + * after clearing RX_CFG_EN before writing to any other RX MAC registers + * or other MAC parameters. alternatively, poll RX_CFG_EN until it clears + * to 0. similary, HASH_FILTER_EN and ADDR_FILTER_EN have the same + * restrictions as CFG_EN. + */ +#define REG_MAC_RX_CFG 0x6034 /* RX MAC config reg */ +#define MAC_RX_CFG_EN 0x0001 /* enable RX MAC */ +#define MAC_RX_CFG_STRIP_PAD 0x0002 /* always program to 0. + feature not supported */ +#define MAC_RX_CFG_STRIP_FCS 0x0004 /* RX MAC will strip the + last 4 bytes of a + received frame. */ +#define MAC_RX_CFG_PROMISC_EN 0x0008 /* promiscuous mode */ +#define MAC_RX_CFG_PROMISC_GROUP_EN 0x0010 /* accept all valid + multicast frames (group + bit in DA field set) */ +#define MAC_RX_CFG_HASH_FILTER_EN 0x0020 /* use hash table to filter + multicast addresses */ +#define MAC_RX_CFG_ADDR_FILTER_EN 0x0040 /* cause RX MAC to use + address filtering regs + to filter both unicast + and multicast + addresses */ +#define MAC_RX_CFG_DISABLE_DISCARD 0x0080 /* pass errored frames to + RX DMA by setting BAD + bit but not Abort bit + in the status. CRC, + framing, and length errs + will not increment + error counters. frames + which don't match dest + addr will be passed up + w/ BAD bit set. */ +#define MAC_RX_CFG_CARRIER_EXTEND 0x0100 /* enable reception of + packet bursts generated + by carrier extension + with packet bursting + senders. only applies + to half-duplex 1Gbps */ + +/* DEFAULT: 0x0 */ +#define REG_MAC_CTRL_CFG 0x6038 /* MAC control config reg */ +#define MAC_CTRL_CFG_SEND_PAUSE_EN 0x0001 /* respond to requests for + sending pause flow ctrl + frames */ +#define MAC_CTRL_CFG_RECV_PAUSE_EN 0x0002 /* respond to received + pause flow ctrl frames */ +#define MAC_CTRL_CFG_PASS_CTRL 0x0004 /* pass valid MAC ctrl + packets to RX DMA */ + +/* to ensure proper operation, a global initialization sequence should be + * performed when a loopback config is entered or exited. if programmed after + * a hw or global sw reset, RX/TX MAC software reset and initialization + * should be done to ensure stable clocking. + * DEFAULT: 0x0 + */ +#define REG_MAC_XIF_CFG 0x603C /* XIF config reg */ +#define MAC_XIF_TX_MII_OUTPUT_EN 0x0001 /* enable output drivers + on MII xmit bus */ +#define MAC_XIF_MII_INT_LOOPBACK 0x0002 /* loopback GMII xmit data + path to GMII recv data + path. phy mode register + clock selection must be + set to GMII mode and + GMII_MODE should be set + to 1. in loopback mode, + REFCLK will drive the + entire mac core. 0 for + normal operation. */ +#define MAC_XIF_DISABLE_ECHO 0x0004 /* disables receive data + path during packet + xmission. clear to 0 + in any full duplex mode, + in any loopback mode, + or in half-duplex SERDES + or SLINK modes. set when + in half-duplex when + using external phy. */ +#define MAC_XIF_GMII_MODE 0x0008 /* MAC operates with GMII + clocks and datapath */ +#define MAC_XIF_MII_BUFFER_OUTPUT_EN 0x0010 /* MII_BUF_EN pin. enable + external tristate buffer + on the MII receive + bus. */ +#define MAC_XIF_LINK_LED 0x0020 /* LINKLED# active (low) */ +#define MAC_XIF_FDPLX_LED 0x0040 /* FDPLXLED# active (low) */ + +#define REG_MAC_IPG0 0x6040 /* inter-packet gap0 reg. + recommended: 0x00 */ +#define REG_MAC_IPG1 0x6044 /* inter-packet gap1 reg + recommended: 0x08 */ +#define REG_MAC_IPG2 0x6048 /* inter-packet gap2 reg + recommended: 0x04 */ +#define REG_MAC_SLOT_TIME 0x604C /* slot time reg + recommended: 0x40 */ +#define REG_MAC_FRAMESIZE_MIN 0x6050 /* min frame size reg + recommended: 0x40 */ + +/* FRAMESIZE_MAX holds both the max frame size as well as the max burst size. + * recommended value: 0x2000.05EE + */ +#define REG_MAC_FRAMESIZE_MAX 0x6054 /* max frame size reg */ +#define MAC_FRAMESIZE_MAX_BURST_MASK 0x3FFF0000 /* max burst size */ +#define MAC_FRAMESIZE_MAX_BURST_SHIFT 16 +#define MAC_FRAMESIZE_MAX_FRAME_MASK 0x00007FFF /* max frame size */ +#define MAC_FRAMESIZE_MAX_FRAME_SHIFT 0 +#define REG_MAC_PA_SIZE 0x6058 /* PA size reg. number of + preamble bytes that the + TX MAC will xmit at the + beginning of each frame + value should be 2 or + greater. recommended + value: 0x07 */ +#define REG_MAC_JAM_SIZE 0x605C /* jam size reg. duration + of jam in units of media + byte time. recommended + value: 0x04 */ +#define REG_MAC_ATTEMPT_LIMIT 0x6060 /* attempt limit reg. # + of attempts TX MAC will + make to xmit a frame + before it resets its + attempts counter. after + the limit has been + reached, TX MAC may or + may not drop the frame + dependent upon value + in TX_MAC_CFG. + recommended + value: 0x10 */ +#define REG_MAC_CTRL_TYPE 0x6064 /* MAC control type reg. + type field of a MAC + ctrl frame. recommended + value: 0x8808 */ + +/* mac address registers: 0 - 44, 0x6080 - 0x6130, 4 8-bit bytes. + * register contains comparison + * 0 16 MSB of primary MAC addr [47:32] of DA field + * 1 16 middle bits "" [31:16] of DA field + * 2 16 LSB "" [15:0] of DA field + * 3*x 16MSB of alt MAC addr 1-15 [47:32] of DA field + * 4*x 16 middle bits "" [31:16] + * 5*x 16 LSB "" [15:0] + * 42 16 MSB of MAC CTRL addr [47:32] of DA. + * 43 16 middle bits "" [31:16] + * 44 16 LSB "" [15:0] + * MAC CTRL addr must be the reserved multicast addr for MAC CTRL frames. + * if there is a match, MAC will set the bit for alternative address + * filter pass [15] + + * here is the map of registers given MAC address notation: a:b:c:d:e:f + * ab cd ef + * primary addr reg 2 reg 1 reg 0 + * alt addr 1 reg 5 reg 4 reg 3 + * alt addr x reg 5*x reg 4*x reg 3*x + * ctrl addr reg 44 reg 43 reg 42 + */ +#define REG_MAC_ADDR0 0x6080 /* MAC address 0 reg */ +#define REG_MAC_ADDRN(x) (REG_MAC_ADDR0 + (x)*4) +#define REG_MAC_ADDR_FILTER0 0x614C /* address filter 0 reg + [47:32] */ +#define REG_MAC_ADDR_FILTER1 0x6150 /* address filter 1 reg + [31:16] */ +#define REG_MAC_ADDR_FILTER2 0x6154 /* address filter 2 reg + [15:0] */ +#define REG_MAC_ADDR_FILTER2_1_MASK 0x6158 /* address filter 2 and 1 + mask reg. 8-bit reg + contains nibble mask for + reg 2 and 1. */ +#define REG_MAC_ADDR_FILTER0_MASK 0x615C /* address filter 0 mask + reg */ + +/* hash table registers: 0 - 15, 0x6160 - 0x619C, 4 8-bit bytes + * 16-bit registers contain bits of the hash table. + * reg x -> [16*(15 - x) + 15 : 16*(15 - x)]. + * e.g., 15 -> [15:0], 0 -> [255:240] + */ +#define REG_MAC_HASH_TABLE0 0x6160 /* hash table 0 reg */ +#define REG_MAC_HASH_TABLEN(x) (REG_MAC_HASH_TABLE0 + (x)*4) + +/* statistics registers. these registers generate an interrupt on + * overflow. recommended initialization: 0x0000. most are 16-bits except + * for PEAK_ATTEMPTS register which is 8 bits. + */ +#define REG_MAC_COLL_NORMAL 0x61A0 /* normal collision + counter. */ +#define REG_MAC_COLL_FIRST 0x61A4 /* first attempt + successful collision + counter */ +#define REG_MAC_COLL_EXCESS 0x61A8 /* excessive collision + counter */ +#define REG_MAC_COLL_LATE 0x61AC /* late collision counter */ +#define REG_MAC_TIMER_DEFER 0x61B0 /* defer timer. time base + is the media byte + clock/256 */ +#define REG_MAC_ATTEMPTS_PEAK 0x61B4 /* peak attempts reg */ +#define REG_MAC_RECV_FRAME 0x61B8 /* receive frame counter */ +#define REG_MAC_LEN_ERR 0x61BC /* length error counter */ +#define REG_MAC_ALIGN_ERR 0x61C0 /* alignment error counter */ +#define REG_MAC_FCS_ERR 0x61C4 /* FCS error counter */ +#define REG_MAC_RX_CODE_ERR 0x61C8 /* RX code violation + error counter */ + +/* misc registers */ +#define REG_MAC_RANDOM_SEED 0x61CC /* random number seed reg. + 10-bit register used as a + seed for the random number + generator for the CSMA/CD + backoff algorithm. only + programmed after power-on + reset and should be a + random value which has a + high likelihood of being + unique for each MAC + attached to a network + segment (e.g., 10 LSB of + MAC address) */ + +/* ASUN: there's a PAUSE_TIMER (ro) described, but it's not in the address + * map + */ + +/* 27-bit register has the current state for key state machines in the MAC */ +#define REG_MAC_STATE_MACHINE 0x61D0 /* (ro) state machine reg */ +#define MAC_SM_RLM_MASK 0x07800000 +#define MAC_SM_RLM_SHIFT 23 +#define MAC_SM_RX_FC_MASK 0x00700000 +#define MAC_SM_RX_FC_SHIFT 20 +#define MAC_SM_TLM_MASK 0x000F0000 +#define MAC_SM_TLM_SHIFT 16 +#define MAC_SM_ENCAP_SM_MASK 0x0000F000 +#define MAC_SM_ENCAP_SM_SHIFT 12 +#define MAC_SM_TX_REQ_MASK 0x00000C00 +#define MAC_SM_TX_REQ_SHIFT 10 +#define MAC_SM_TX_FC_MASK 0x000003C0 +#define MAC_SM_TX_FC_SHIFT 6 +#define MAC_SM_FIFO_WRITE_SEL_MASK 0x00000038 +#define MAC_SM_FIFO_WRITE_SEL_SHIFT 3 +#define MAC_SM_TX_FIFO_EMPTY_MASK 0x00000007 +#define MAC_SM_TX_FIFO_EMPTY_SHIFT 0 + +/** MIF registers. the MIF can be programmed in either bit-bang or + * frame mode. + **/ +#define REG_MIF_BIT_BANG_CLOCK 0x6200 /* MIF bit-bang clock. + 1 -> 0 will generate a + rising edge. 0 -> 1 will + generate a falling edge. */ +#define REG_MIF_BIT_BANG_DATA 0x6204 /* MIF bit-bang data. 1-bit + register generates data */ +#define REG_MIF_BIT_BANG_OUTPUT_EN 0x6208 /* MIF bit-bang output + enable. enable when + xmitting data from MIF to + transceiver. */ + +/* 32-bit register serves as an instruction register when the MIF is + * programmed in frame mode. load this register w/ a valid instruction + * (as per IEEE 802.3u MII spec). poll this register to check for instruction + * execution completion. during a read operation, this register will also + * contain the 16-bit data returned by the tranceiver. unless specified + * otherwise, fields are considered "don't care" when polling for + * completion. + */ +#define REG_MIF_FRAME 0x620C /* MIF frame/output reg */ +#define MIF_FRAME_START_MASK 0xC0000000 /* start of frame. + load w/ 01 when + issuing an instr */ +#define MIF_FRAME_ST 0x40000000 /* STart of frame */ +#define MIF_FRAME_OPCODE_MASK 0x30000000 /* opcode. 01 for a + write. 10 for a + read */ +#define MIF_FRAME_OP_READ 0x20000000 /* read OPcode */ +#define MIF_FRAME_OP_WRITE 0x10000000 /* write OPcode */ +#define MIF_FRAME_PHY_ADDR_MASK 0x0F800000 /* phy address. when + issuing an instr, + this field should be + loaded w/ the XCVR + addr */ +#define MIF_FRAME_PHY_ADDR_SHIFT 23 +#define MIF_FRAME_REG_ADDR_MASK 0x007C0000 /* register address. + when issuing an instr, + addr of register + to be read/written */ +#define MIF_FRAME_REG_ADDR_SHIFT 18 +#define MIF_FRAME_TURN_AROUND_MSB 0x00020000 /* turn around, MSB. + when issuing an instr, + set this bit to 1 */ +#define MIF_FRAME_TURN_AROUND_LSB 0x00010000 /* turn around, LSB. + when issuing an instr, + set this bit to 0. + when polling for + completion, 1 means + that instr execution + has been completed */ +#define MIF_FRAME_DATA_MASK 0x0000FFFF /* instruction payload + load with 16-bit data + to be written in + transceiver reg for a + write. doesn't matter + in a read. when + polling for + completion, field is + "don't care" for write + and 16-bit data + returned by the + transceiver for a + read (if valid bit + is set) */ +#define REG_MIF_CFG 0x6210 /* MIF config reg */ +#define MIF_CFG_PHY_SELECT 0x0001 /* 1 -> select MDIO_1 + 0 -> select MDIO_0 */ +#define MIF_CFG_POLL_EN 0x0002 /* enable polling + mechanism. if set, + BB_MODE should be 0 */ +#define MIF_CFG_BB_MODE 0x0004 /* 1 -> bit-bang mode + 0 -> frame mode */ +#define MIF_CFG_POLL_REG_MASK 0x00F8 /* register address to be + used by polling mode. + only meaningful if POLL_EN + is set to 1 */ +#define MIF_CFG_POLL_REG_SHIFT 3 +#define MIF_CFG_MDIO_0 0x0100 /* (ro) dual purpose. + when MDIO_0 is idle, + 1 -> tranceiver is + connected to MDIO_0. + when MIF is communicating + w/ MDIO_0 in bit-bang + mode, this bit indicates + the incoming bit stream + during a read op */ +#define MIF_CFG_MDIO_1 0x0200 /* (ro) dual purpose. + when MDIO_1 is idle, + 1 -> transceiver is + connected to MDIO_1. + when MIF is communicating + w/ MDIO_1 in bit-bang + mode, this bit indicates + the incoming bit stream + during a read op */ +#define MIF_CFG_POLL_PHY_MASK 0x7C00 /* tranceiver address to + be polled */ +#define MIF_CFG_POLL_PHY_SHIFT 10 + +/* 16-bit register used to determine which bits in the POLL_STATUS portion of + * the MIF_STATUS register will cause an interrupt. if a mask bit is 0, + * corresponding bit of the POLL_STATUS will generate a MIF interrupt when + * set. DEFAULT: 0xFFFF + */ +#define REG_MIF_MASK 0x6214 /* MIF mask reg */ + +/* 32-bit register used when in poll mode. auto-cleared after being read */ +#define REG_MIF_STATUS 0x6218 /* MIF status reg */ +#define MIF_STATUS_POLL_DATA_MASK 0xFFFF0000 /* poll data contains + the "latest image" + update of the XCVR + reg being read */ +#define MIF_STATUS_POLL_DATA_SHIFT 16 +#define MIF_STATUS_POLL_STATUS_MASK 0x0000FFFF /* poll status indicates + which bits in the + POLL_DATA field have + changed since the + MIF_STATUS reg was + last read */ +#define MIF_STATUS_POLL_STATUS_SHIFT 0 + +/* 7-bit register has current state for all state machines in the MIF */ +#define REG_MIF_STATE_MACHINE 0x621C /* MIF state machine reg */ +#define MIF_SM_CONTROL_MASK 0x07 /* control state machine + state */ +#define MIF_SM_EXECUTION_MASK 0x60 /* execution state machine + state */ + +/** PCS/Serialink. the following registers are equivalent to the standard + * MII management registers except that they're directly mapped in + * Cassini's register space. + **/ + +/* the auto-negotiation enable bit should be programmed the same at + * the link partner as in the local device to enable auto-negotiation to + * complete. when that bit is reprogrammed, auto-neg/manual config is + * restarted automatically. + * DEFAULT: 0x1040 + */ +#define REG_PCS_MII_CTRL 0x9000 /* PCS MII control reg */ +#define PCS_MII_CTRL_1000_SEL 0x0040 /* reads 1. ignored on + writes */ +#define PCS_MII_CTRL_COLLISION_TEST 0x0080 /* COL signal at the PCS + to MAC interface is + activated regardless + of activity */ +#define PCS_MII_CTRL_DUPLEX 0x0100 /* forced 0x0. PCS + behaviour same for + half and full dplx */ +#define PCS_MII_RESTART_AUTONEG 0x0200 /* self clearing. + restart auto- + negotiation */ +#define PCS_MII_ISOLATE 0x0400 /* read as 0. ignored + on writes */ +#define PCS_MII_POWER_DOWN 0x0800 /* read as 0. ignored + on writes */ +#define PCS_MII_AUTONEG_EN 0x1000 /* default 1. PCS goes + through automatic + link config before it + can be used. when 0, + link can be used + w/out any link config + phase */ +#define PCS_MII_10_100_SEL 0x2000 /* read as 0. ignored on + writes */ +#define PCS_MII_RESET 0x8000 /* reset PCS. self-clears + when done */ + +/* DEFAULT: 0x0108 */ +#define REG_PCS_MII_STATUS 0x9004 /* PCS MII status reg */ +#define PCS_MII_STATUS_EXTEND_CAP 0x0001 /* reads 0 */ +#define PCS_MII_STATUS_JABBER_DETECT 0x0002 /* reads 0 */ +#define PCS_MII_STATUS_LINK_STATUS 0x0004 /* 1 -> link up. + 0 -> link down. 0 is + latched so that 0 is + kept until read. read + 2x to determine if the + link has gone up again */ +#define PCS_MII_STATUS_AUTONEG_ABLE 0x0008 /* reads 1 (able to perform + auto-neg) */ +#define PCS_MII_STATUS_REMOTE_FAULT 0x0010 /* 1 -> remote fault detected + from received link code + word. only valid after + auto-neg completed */ +#define PCS_MII_STATUS_AUTONEG_COMP 0x0020 /* 1 -> auto-negotiation + completed + 0 -> auto-negotiation not + completed */ +#define PCS_MII_STATUS_EXTEND_STATUS 0x0100 /* reads as 1. used as an + indication that this is + a 1000 Base-X PHY. writes + to it are ignored */ + +/* used during auto-negotiation. + * DEFAULT: 0x00E0 + */ +#define REG_PCS_MII_ADVERT 0x9008 /* PCS MII advertisement + reg */ +#define PCS_MII_ADVERT_FD 0x0020 /* advertise full duplex + 1000 Base-X */ +#define PCS_MII_ADVERT_HD 0x0040 /* advertise half-duplex + 1000 Base-X */ +#define PCS_MII_ADVERT_SYM_PAUSE 0x0080 /* advertise PAUSE + symmetric capability */ +#define PCS_MII_ADVERT_ASYM_PAUSE 0x0100 /* advertises PAUSE + asymmetric capability */ +#define PCS_MII_ADVERT_RF_MASK 0x3000 /* remote fault. write bit13 + to optionally indicate to + link partner that chip is + going off-line. bit12 will + get set when signal + detect == FAIL and will + remain set until + successful negotiation */ +#define PCS_MII_ADVERT_ACK 0x4000 /* (ro) */ +#define PCS_MII_ADVERT_NEXT_PAGE 0x8000 /* (ro) forced 0x0 */ + +/* contents updated as a result of autonegotiation. layout and definitions + * identical to PCS_MII_ADVERT + */ +#define REG_PCS_MII_LPA 0x900C /* PCS MII link partner + ability reg */ +#define PCS_MII_LPA_FD PCS_MII_ADVERT_FD +#define PCS_MII_LPA_HD PCS_MII_ADVERT_HD +#define PCS_MII_LPA_SYM_PAUSE PCS_MII_ADVERT_SYM_PAUSE +#define PCS_MII_LPA_ASYM_PAUSE PCS_MII_ADVERT_ASYM_PAUSE +#define PCS_MII_LPA_RF_MASK PCS_MII_ADVERT_RF_MASK +#define PCS_MII_LPA_ACK PCS_MII_ADVERT_ACK +#define PCS_MII_LPA_NEXT_PAGE PCS_MII_ADVERT_NEXT_PAGE + +/* DEFAULT: 0x0 */ +#define REG_PCS_CFG 0x9010 /* PCS config reg */ +#define PCS_CFG_EN 0x01 /* enable PCS. must be + 0 when modifying + PCS_MII_ADVERT */ +#define PCS_CFG_SD_OVERRIDE 0x02 /* sets signal detect to + OK. bit is + non-resettable */ +#define PCS_CFG_SD_ACTIVE_LOW 0x04 /* changes interpretation + of optical signal to make + signal detect okay when + signal is low */ +#define PCS_CFG_JITTER_STUDY_MASK 0x18 /* used to make jitter + measurements. a single + code group is xmitted + regularly. + 0x0 = normal operation + 0x1 = high freq test + pattern, D21.5 + 0x2 = low freq test + pattern, K28.7 + 0x3 = reserved */ +#define PCS_CFG_10MS_TIMER_OVERRIDE 0x20 /* shortens 10-20ms auto- + negotiation timer to + a few cycles for test + purposes */ + +/* used for diagnostic purposes. bits 20-22 autoclear on read */ +#define REG_PCS_STATE_MACHINE 0x9014 /* (ro) PCS state machine + and diagnostic reg */ +#define PCS_SM_TX_STATE_MASK 0x0000000F /* 0 and 1 indicate + xmission of idle. + otherwise, xmission of + a packet */ +#define PCS_SM_RX_STATE_MASK 0x000000F0 /* 0 indicates reception + of idle. otherwise, + reception of packet */ +#define PCS_SM_WORD_SYNC_STATE_MASK 0x00000700 /* 0 indicates loss of + sync */ +#define PCS_SM_SEQ_DETECT_STATE_MASK 0x00001800 /* cycling through 0-3 + indicates reception of + Config codes. cycling + through 0-1 indicates + reception of idles */ +#define PCS_SM_LINK_STATE_MASK 0x0001E000 +#define SM_LINK_STATE_UP 0x00016000 /* link state is up */ + +#define PCS_SM_LOSS_LINK_C 0x00100000 /* loss of link due to + recept of Config + codes */ +#define PCS_SM_LOSS_LINK_SYNC 0x00200000 /* loss of link due to + loss of sync */ +#define PCS_SM_LOSS_SIGNAL_DETECT 0x00400000 /* signal detect goes + from OK to FAIL. bit29 + will also be set if + this is set */ +#define PCS_SM_NO_LINK_BREAKLINK 0x01000000 /* link not up due to + receipt of breaklink + C codes from partner. + C codes w/ 0 content + received triggering + start/restart of + autonegotiation. + should be sent for + no longer than 20ms */ +#define PCS_SM_NO_LINK_SERDES 0x02000000 /* serdes being + initialized. see serdes + state reg */ +#define PCS_SM_NO_LINK_C 0x04000000 /* C codes not stable or + not received */ +#define PCS_SM_NO_LINK_SYNC 0x08000000 /* word sync not + achieved */ +#define PCS_SM_NO_LINK_WAIT_C 0x10000000 /* waiting for C codes + w/ ack bit set */ +#define PCS_SM_NO_LINK_NO_IDLE 0x20000000 /* link partner continues + to send C codes + instead of idle + symbols or pkt data */ + +/* this register indicates interrupt changes in specific PCS MII status bits. + * PCS_INT may be masked at the ISR level. only a single bit is implemented + * for link status change. + */ +#define REG_PCS_INTR_STATUS 0x9018 /* PCS interrupt status */ +#define PCS_INTR_STATUS_LINK_CHANGE 0x04 /* link status has changed + since last read */ + +/* control which network interface is used. no more than one bit should + * be set. + * DEFAULT: none + */ +#define REG_PCS_DATAPATH_MODE 0x9050 /* datapath mode reg */ +#define PCS_DATAPATH_MODE_MII 0x00 /* PCS is not used and + MII/GMII is selected. + selection between MII and + GMII is controlled by + XIF_CFG */ +#define PCS_DATAPATH_MODE_SERDES 0x02 /* PCS is used via the + 10-bit interface */ + +/* input to serdes chip or serialink block */ +#define REG_PCS_SERDES_CTRL 0x9054 /* serdes control reg */ +#define PCS_SERDES_CTRL_LOOPBACK 0x01 /* enable loopback on + serdes interface */ +#define PCS_SERDES_CTRL_SYNCD_EN 0x02 /* enable sync carrier + detection. should be + 0x0 for normal + operation */ +#define PCS_SERDES_CTRL_LOCKREF 0x04 /* frequency-lock RBC[0:1] + to REFCLK when set. + when clear, receiver + clock locks to incoming + serial data */ + +/* multiplex test outputs into the PROM address (PA_3 through PA_0) pins. + * should be 0x0 for normal operations. + * 0b000 normal operation, PROM address[3:0] selected + * 0b001 rxdma req, rxdma ack, rxdma ready, rxdma read + * 0b010 rxmac req, rx ack, rx tag, rx clk shared + * 0b011 txmac req, tx ack, tx tag, tx retry req + * 0b100 tx tp3, tx tp2, tx tp1, tx tp0 + * 0b101 R period RX, R period TX, R period HP, R period BIM + * DEFAULT: 0x0 + */ +#define REG_PCS_SHARED_OUTPUT_SEL 0x9058 /* shared output select */ +#define PCS_SOS_PROM_ADDR_MASK 0x0007 + +/* used for diagnostics. this register indicates progress of the SERDES + * boot up. + * 0b00 undergoing reset + * 0b01 waiting 500us while lockrefn is asserted + * 0b10 waiting for comma detect + * 0b11 receive data is synchronized + * DEFAULT: 0x0 + */ +#define REG_PCS_SERDES_STATE 0x905C /* (ro) serdes state */ +#define PCS_SERDES_STATE_MASK 0x03 + +/* used for diagnostics. indicates number of packets transmitted or received. + * counters rollover w/out generating an interrupt. + * DEFAULT: 0x0 + */ +#define REG_PCS_PACKET_COUNT 0x9060 /* (ro) PCS packet counter */ +#define PCS_PACKET_COUNT_TX 0x000007FF /* pkts xmitted by PCS */ +#define PCS_PACKET_COUNT_RX 0x07FF0000 /* pkts recvd by PCS + whether they + encountered an error + or not */ + +/** LocalBus Devices. the following provides run-time access to the + * Cassini's PROM + ***/ +#define REG_EXPANSION_ROM_RUN_START 0x100000 /* expansion rom run time + access */ +#define REG_EXPANSION_ROM_RUN_END 0x17FFFF + +#define REG_SECOND_LOCALBUS_START 0x180000 /* secondary local bus + device */ +#define REG_SECOND_LOCALBUS_END 0x1FFFFF + +/* entropy device */ +#define REG_ENTROPY_START REG_SECOND_LOCALBUS_START +#define REG_ENTROPY_DATA (REG_ENTROPY_START + 0x00) +#define REG_ENTROPY_STATUS (REG_ENTROPY_START + 0x04) +#define ENTROPY_STATUS_DRDY 0x01 +#define ENTROPY_STATUS_BUSY 0x02 +#define ENTROPY_STATUS_CIPHER 0x04 +#define ENTROPY_STATUS_BYPASS_MASK 0x18 +#define REG_ENTROPY_MODE (REG_ENTROPY_START + 0x05) +#define ENTROPY_MODE_KEY_MASK 0x07 +#define ENTROPY_MODE_ENCRYPT 0x40 +#define REG_ENTROPY_RAND_REG (REG_ENTROPY_START + 0x06) +#define REG_ENTROPY_RESET (REG_ENTROPY_START + 0x07) +#define ENTROPY_RESET_DES_IO 0x01 +#define ENTROPY_RESET_STC_MODE 0x02 +#define ENTROPY_RESET_KEY_CACHE 0x04 +#define ENTROPY_RESET_IV 0x08 +#define REG_ENTROPY_IV (REG_ENTROPY_START + 0x08) +#define REG_ENTROPY_KEY0 (REG_ENTROPY_START + 0x10) +#define REG_ENTROPY_KEYN(x) (REG_ENTROPY_KEY0 + 4*(x)) + +/* phys of interest w/ their special mii registers */ +#define PHY_LUCENT_B0 0x00437421 +#define LUCENT_MII_REG 0x1F + +#define PHY_NS_DP83065 0x20005c78 +#define DP83065_MII_MEM 0x16 +#define DP83065_MII_REGD 0x1D +#define DP83065_MII_REGE 0x1E + +#define PHY_BROADCOM_5411 0x00206071 +#define PHY_BROADCOM_B0 0x00206050 +#define BROADCOM_MII_REG4 0x14 +#define BROADCOM_MII_REG5 0x15 +#define BROADCOM_MII_REG7 0x17 +#define BROADCOM_MII_REG8 0x18 + +#define CAS_MII_ANNPTR 0x07 +#define CAS_MII_ANNPRR 0x08 +#define CAS_MII_1000_CTRL 0x09 +#define CAS_MII_1000_STATUS 0x0A +#define CAS_MII_1000_EXTEND 0x0F + +#define CAS_BMSR_1000_EXTEND 0x0100 /* supports 1000Base-T extended status */ +/* + * if autoneg is disabled, here's the table: + * BMCR_SPEED100 = 100Mbps + * BMCR_SPEED1000 = 1000Mbps + * ~(BMCR_SPEED100 | BMCR_SPEED1000) = 10Mbps + */ +#define CAS_BMCR_SPEED1000 0x0040 /* Select 1000Mbps */ + +#define CAS_ADVERTISE_1000HALF 0x0100 +#define CAS_ADVERTISE_1000FULL 0x0200 +#define CAS_ADVERTISE_PAUSE 0x0400 +#define CAS_ADVERTISE_ASYM_PAUSE 0x0800 + +/* regular lpa register */ +#define CAS_LPA_PAUSE CAS_ADVERTISE_PAUSE +#define CAS_LPA_ASYM_PAUSE CAS_ADVERTISE_ASYM_PAUSE + +/* 1000_STATUS register */ +#define CAS_LPA_1000HALF 0x0400 +#define CAS_LPA_1000FULL 0x0800 + +#define CAS_EXTEND_1000XFULL 0x8000 +#define CAS_EXTEND_1000XHALF 0x4000 +#define CAS_EXTEND_1000TFULL 0x2000 +#define CAS_EXTEND_1000THALF 0x1000 + +/* cassini header parser firmware */ +typedef struct cas_hp_inst { + const char *note; + + u16 mask, val; + + u8 op; + u8 soff, snext; /* if match succeeds, new offset and match */ + u8 foff, fnext; /* if match fails, new offset and match */ + /* output info */ + u8 outop; /* output opcode */ + + u16 outarg; /* output argument */ + u8 outenab; /* output enable: 0 = not, 1 = if match + 2 = if !match, 3 = always */ + u8 outshift; /* barrel shift right, 4 bits */ + u16 outmask; +} cas_hp_inst_t; + +/* comparison */ +#define OP_EQ 0 /* packet == value */ +#define OP_LT 1 /* packet < value */ +#define OP_GT 2 /* packet > value */ +#define OP_NP 3 /* new packet */ + +/* output opcodes */ +#define CL_REG 0 +#define LD_FID 1 +#define LD_SEQ 2 +#define LD_CTL 3 +#define LD_SAP 4 +#define LD_R1 5 +#define LD_L3 6 +#define LD_SUM 7 +#define LD_HDR 8 +#define IM_FID 9 +#define IM_SEQ 10 +#define IM_SAP 11 +#define IM_R1 12 +#define IM_CTL 13 +#define LD_LEN 14 +#define ST_FLG 15 + +/* match setp #s for IP4TCP4 */ +#define S1_PCKT 0 +#define S1_VLAN 1 +#define S1_CFI 2 +#define S1_8023 3 +#define S1_LLC 4 +#define S1_LLCc 5 +#define S1_IPV4 6 +#define S1_IPV4c 7 +#define S1_IPV4F 8 +#define S1_TCP44 9 +#define S1_IPV6 10 +#define S1_IPV6L 11 +#define S1_IPV6c 12 +#define S1_TCP64 13 +#define S1_TCPSQ 14 +#define S1_TCPFG 15 +#define S1_TCPHL 16 +#define S1_TCPHc 17 +#define S1_CLNP 18 +#define S1_CLNP2 19 +#define S1_DROP 20 +#define S2_HTTP 21 +#define S1_ESP4 22 +#define S1_AH4 23 +#define S1_ESP6 24 +#define S1_AH6 25 + +#define CAS_PROG_IP46TCP4_PREAMBLE \ +{ "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, S1_PCKT, \ + CL_REG, 0x3ff, 1, 0x0, 0x0000}, \ +{ "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023, \ + IM_CTL, 0x00a, 3, 0x0, 0xffff}, \ +{ "CFI?", 0x1000, 0x1000, OP_EQ, 0, S1_DROP, 1, S1_8023, \ + CL_REG, 0x000, 0, 0x0, 0x0000}, \ +{ "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4, \ + CL_REG, 0x000, 0, 0x0, 0x0000}, \ +{ "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP, \ + CL_REG, 0x000, 0, 0x0, 0x0000}, \ +{ "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP, \ + CL_REG, 0x000, 0, 0x0, 0x0000}, \ +{ "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6, \ + LD_SAP, 0x100, 3, 0x0, 0xffff}, \ +{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP, \ + LD_SUM, 0x00a, 1, 0x0, 0x0000}, \ +{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP, \ + LD_LEN, 0x03e, 1, 0x0, 0xffff}, \ +{ "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_CLNP, \ + LD_FID, 0x182, 1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ \ +{ "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP, \ + LD_SUM, 0x015, 1, 0x0, 0x0000}, \ +{ "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP, \ + IM_R1, 0x128, 1, 0x0, 0xffff}, \ +{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP, \ + LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ \ +{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP, \ + LD_LEN, 0x03f, 1, 0x0, 0xffff} + +#ifdef USE_HP_IP46TCP4 +static cas_hp_inst_t cas_prog_ip46tcp4tab[] = { + CAS_PROG_IP46TCP4_PREAMBLE, + { "TCP seq", /* DADDR should point to dest port */ + 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */ + { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0, + S1_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, + S1_TCPHc, LD_R1, 0x205, 3, 0xB, 0xf000}, + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, + S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff}, + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x000, 0, 0x0, 0x0000}, + { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x080, 3, 0x0, 0xffff}, + { NULL }, +}; +#ifdef HP_IP46TCP4_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_ip46tcp4tab +#endif +#endif + +/* + * Alternate table load which excludes HTTP server traffic from reassembly. + * It is substantially similar to the basic table, with one extra state + * and a few extra compares. */ +#ifdef USE_HP_IP46TCP4NOHTTP +static cas_hp_inst_t cas_prog_ip46tcp4nohttptab[] = { + CAS_PROG_IP46TCP4_PREAMBLE, + { "TCP seq", /* DADDR should point to dest port */ + 0xFFFF, 0x0080, OP_EQ, 0, S2_HTTP, 0, S1_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff} , /* Load TCP seq # */ + { "TCP control flags", 0xFFFF, 0x8080, OP_EQ, 0, S2_HTTP, 0, + S1_TCPHL, ST_FLG, 0x145, 2, 0x0, 0x002f, }, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc, + LD_R1, 0x205, 3, 0xB, 0xf000}, + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + LD_HDR, 0x0ff, 3, 0x0, 0xffff}, + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + CL_REG, 0x002, 3, 0x0, 0x0000}, + { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x080, 3, 0x0, 0xffff}, + { "No HTTP", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x044, 3, 0x0, 0xffff}, + { NULL }, +}; +#ifdef HP_IP46TCP4NOHTTP_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_ip46tcp4nohttptab +#endif +#endif + +/* match step #s for IP4FRAG */ +#define S3_IPV6c 11 +#define S3_TCP64 12 +#define S3_TCPSQ 13 +#define S3_TCPFG 14 +#define S3_TCPHL 15 +#define S3_TCPHc 16 +#define S3_FRAG 17 +#define S3_FOFF 18 +#define S3_CLNP 19 + +#ifdef USE_HP_IP4FRAG +static cas_hp_inst_t cas_prog_ip4fragtab[] = { + { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, S1_PCKT, + CL_REG, 0x3ff, 1, 0x0, 0x0000}, + { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023, + IM_CTL, 0x00a, 3, 0x0, 0xffff}, + { "CFI?", 0x1000, 0x1000, OP_EQ, 0, S3_CLNP, 1, S1_8023, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S3_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLCc?",0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S3_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6, + LD_SAP, 0x100, 3, 0x0, 0xffff}, + { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S3_CLNP, + LD_SUM, 0x00a, 1, 0x0, 0x0000}, + { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S3_FRAG, + LD_LEN, 0x03e, 3, 0x0, 0xffff}, + { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S3_TCPSQ, 0, S3_CLNP, + LD_FID, 0x182, 3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ + { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S3_IPV6c, 0, S3_CLNP, + LD_SUM, 0x015, 1, 0x0, 0x0000}, + { "IPV6 cont?", 0xf000, 0x6000, OP_EQ, 3, S3_TCP64, 0, S3_CLNP, + LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ + { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S3_TCPSQ, 0, S3_CLNP, + LD_LEN, 0x03f, 1, 0x0, 0xffff}, + { "TCP seq", /* DADDR should point to dest port */ + 0x0000, 0x0000, OP_EQ, 0, S3_TCPFG, 4, S3_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */ + { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S3_TCPHL, 0, + S3_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S3_TCPHc, 0, S3_TCPHc, + LD_R1, 0x205, 3, 0xB, 0xf000}, + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + LD_HDR, 0x0ff, 3, 0x0, 0xffff}, + { "IP4 Fragment", 0x0000, 0x0000, OP_EQ, 0, S3_FOFF, 0, S3_FOFF, + LD_FID, 0x103, 3, 0x0, 0xffff}, /* FID IP4 src+dst */ + { "IP4 frag offset", 0x0000, 0x0000, OP_EQ, 0, S3_FOFF, 0, S3_FOFF, + LD_SEQ, 0x040, 1, 0xD, 0xfff8}, + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { NULL }, +}; +#ifdef HP_IP4FRAG_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_ip4fragtab +#endif +#endif + +/* + * Alternate table which does batching without reassembly + */ +#ifdef USE_HP_IP46TCP4BATCH +static cas_hp_inst_t cas_prog_ip46tcp4batchtab[] = { + CAS_PROG_IP46TCP4_PREAMBLE, + { "TCP seq", /* DADDR should point to dest port */ + 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 0, S1_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */ + { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0, + S1_TCPHL, ST_FLG, 0x000, 3, 0x0, 0x0000}, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, + S1_TCPHc, LD_R1, 0x205, 3, 0xB, 0xf000}, + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, + S1_PCKT, IM_CTL, 0x040, 3, 0x0, 0xffff}, /* set batch bit */ + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, + S1_PCKT, IM_CTL, 0x080, 3, 0x0, 0xffff}, + { NULL }, +}; +#ifdef HP_IP46TCP4BATCH_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_ip46tcp4batchtab +#endif +#endif + +/* Workaround for Cassini rev2 descriptor corruption problem. + * Does batching without reassembly, and sets the SAP to a known + * data pattern for all packets. + */ +#ifdef USE_HP_WORKAROUND +static cas_hp_inst_t cas_prog_workaroundtab[] = { + { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, + S1_PCKT, CL_REG, 0x3ff, 1, 0x0, 0x0000} , + { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023, + IM_CTL, 0x04a, 3, 0x0, 0xffff}, + { "CFI?", 0x1000, 0x1000, OP_EQ, 0, S1_CLNP, 1, S1_8023, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6, + IM_SAP, 0x6AE, 3, 0x0, 0xffff}, + { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP, + LD_SUM, 0x00a, 1, 0x0, 0x0000}, + { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP, + LD_LEN, 0x03e, 1, 0x0, 0xffff}, + { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_CLNP, + LD_FID, 0x182, 3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ + { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP, + LD_SUM, 0x015, 1, 0x0, 0x0000}, + { "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP, + IM_R1, 0x128, 1, 0x0, 0xffff}, + { "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP, + LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ + { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP, + LD_LEN, 0x03f, 1, 0x0, 0xffff}, + { "TCP seq", /* DADDR should point to dest port */ + 0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */ + { "TCP control flags", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHL, 0, + S1_TCPHL, ST_FLG, 0x045, 3, 0x0, 0x002f}, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc, + LD_R1, 0x205, 3, 0xB, 0xf000}, + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, + S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff}, + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2, + IM_SAP, 0x6AE, 3, 0x0, 0xffff} , + { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { NULL }, +}; +#ifdef HP_WORKAROUND_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_workaroundtab +#endif +#endif + +#ifdef USE_HP_ENCRYPT +static cas_hp_inst_t cas_prog_encryptiontab[] = { + { "packet arrival?", 0xffff, 0x0000, OP_NP, 6, S1_VLAN, 0, + S1_PCKT, CL_REG, 0x3ff, 1, 0x0, 0x0000}, + { "VLAN?", 0xffff, 0x8100, OP_EQ, 1, S1_CFI, 0, S1_8023, + IM_CTL, 0x00a, 3, 0x0, 0xffff}, +#if 0 +//"CFI?", /* 02 FIND CFI and If FIND go to S1_DROP */ +//0x1000, 0x1000, OP_EQ, 0, S1_DROP, 1, S1_8023, CL_REG, 0x000, 0, 0x0, 0x00 + 00, +#endif + { "CFI?", /* FIND CFI and If FIND go to CleanUP1 (ignore and send to host) */ + 0x1000, 0x1000, OP_EQ, 0, S1_CLNP, 1, S1_8023, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "8023?", 0xffff, 0x0600, OP_LT, 1, S1_LLC, 0, S1_IPV4, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLC?", 0xffff, 0xaaaa, OP_EQ, 1, S1_LLCc, 0, S1_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "LLCc?", 0xff00, 0x0300, OP_EQ, 2, S1_IPV4, 0, S1_CLNP, + CL_REG, 0x000, 0, 0x0, 0x0000}, + { "IPV4?", 0xffff, 0x0800, OP_EQ, 1, S1_IPV4c, 0, S1_IPV6, + LD_SAP, 0x100, 3, 0x0, 0xffff}, + { "IPV4 cont?", 0xff00, 0x4500, OP_EQ, 3, S1_IPV4F, 0, S1_CLNP, + LD_SUM, 0x00a, 1, 0x0, 0x0000}, + { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ, 1, S1_TCP44, 0, S1_CLNP, + LD_LEN, 0x03e, 1, 0x0, 0xffff}, + { "TCP44?", 0x00ff, 0x0006, OP_EQ, 7, S1_TCPSQ, 0, S1_ESP4, + LD_FID, 0x182, 1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ + { "IPV6?", 0xffff, 0x86dd, OP_EQ, 1, S1_IPV6L, 0, S1_CLNP, + LD_SUM, 0x015, 1, 0x0, 0x0000}, + { "IPV6 len", 0xf000, 0x6000, OP_EQ, 0, S1_IPV6c, 0, S1_CLNP, + IM_R1, 0x128, 1, 0x0, 0xffff}, + { "IPV6 cont?", 0x0000, 0x0000, OP_EQ, 3, S1_TCP64, 0, S1_CLNP, + LD_FID, 0x484, 1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ + { "TCP64?", +#if 0 +//@@@0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_ESP6, LD_LEN, 0x03f, 1, 0x0, 0xffff, +#endif + 0xff00, 0x0600, OP_EQ, 12, S1_TCPSQ, 0, S1_ESP6, LD_LEN, + 0x03f, 1, 0x0, 0xffff}, + { "TCP seq", /* 14:DADDR should point to dest port */ + 0xFFFF, 0x0080, OP_EQ, 0, S2_HTTP, 0, S1_TCPFG, LD_SEQ, + 0x081, 3, 0x0, 0xffff}, /* Load TCP seq # */ + { "TCP control flags", 0xFFFF, 0x8080, OP_EQ, 0, S2_HTTP, 0, + S1_TCPHL, ST_FLG, 0x145, 2, 0x0, 0x002f}, /* Load TCP flags */ + { "TCP length", 0x0000, 0x0000, OP_EQ, 0, S1_TCPHc, 0, S1_TCPHc, + LD_R1, 0x205, 3, 0xB, 0xf000} , + { "TCP length cont", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, + S1_PCKT, LD_HDR, 0x0ff, 3, 0x0, 0xffff}, + { "Cleanup", 0x0000, 0x0000, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP2, + IM_CTL, 0x001, 3, 0x0, 0x0001}, + { "Cleanup 2", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + CL_REG, 0x002, 3, 0x0, 0x0000}, + { "Drop packet", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x080, 3, 0x0, 0xffff}, + { "No HTTP", 0x0000, 0x0000, OP_EQ, 0, S1_PCKT, 0, S1_PCKT, + IM_CTL, 0x044, 3, 0x0, 0xffff}, + { "IPV4 ESP encrypted?", /* S1_ESP4 */ + 0x00ff, 0x0032, OP_EQ, 0, S1_CLNP2, 0, S1_AH4, IM_CTL, + 0x021, 1, 0x0, 0xffff}, + { "IPV4 AH encrypted?", /* S1_AH4 */ + 0x00ff, 0x0033, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL, + 0x021, 1, 0x0, 0xffff}, + { "IPV6 ESP encrypted?", /* S1_ESP6 */ +#if 0 +//@@@0x00ff, 0x0032, OP_EQ, 0, S1_CLNP2, 0, S1_AH6, IM_CTL, 0x021, 1, 0x0, 0xffff, +#endif + 0xff00, 0x3200, OP_EQ, 0, S1_CLNP2, 0, S1_AH6, IM_CTL, + 0x021, 1, 0x0, 0xffff}, + { "IPV6 AH encrypted?", /* S1_AH6 */ +#if 0 +//@@@0x00ff, 0x0033, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL, 0x021, 1, 0x0, 0xffff, +#endif + 0xff00, 0x3300, OP_EQ, 0, S1_CLNP2, 0, S1_CLNP, IM_CTL, + 0x021, 1, 0x0, 0xffff}, + { NULL }, +}; +#ifdef HP_ENCRYPT_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_encryptiontab +#endif +#endif + +static cas_hp_inst_t cas_prog_null[] = { {NULL} }; +#ifdef HP_NULL_DEFAULT +#define CAS_HP_FIRMWARE cas_prog_null +#endif + +/* firmware patch for NS_DP83065 */ +typedef struct cas_saturn_patch { + u16 addr; + u16 val; +} cas_saturn_patch_t; + +#if 1 +cas_saturn_patch_t cas_saturn_patch[] = { +{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009}, +{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000}, +{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000}, +{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff}, +{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025}, +{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f}, +{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026}, +{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011}, +{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d}, +{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086}, +{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f}, +{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3}, +{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047}, +{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a}, +{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047}, +{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033}, +{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f}, +{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084}, +{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004}, +{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096}, +{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c}, +{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027}, +{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084}, +{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047}, +{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a}, +{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047}, +{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054}, +{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f}, +{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084}, +{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004}, +{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6}, +{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084}, +{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003}, +{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025}, +{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6}, +{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f}, +{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7}, +{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f}, +{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec}, +{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa}, +{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7}, +{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082}, +{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001}, +{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046}, +{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081}, +{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a}, +{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020}, +{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027}, +{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084}, +{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7}, +{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084}, +{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047}, +{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a}, +{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047}, +{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad}, +{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082}, +{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001}, +{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084}, +{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041}, +{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026}, +{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023}, +{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027}, +{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed}, +{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083}, +{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042}, +{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e}, +{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084}, +{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003}, +{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df}, +{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6}, +{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f}, +{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7}, +{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f}, +{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec}, +{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa}, +{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011}, +{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd}, +{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce}, +{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff}, +{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096}, +{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c}, +{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027}, +{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049}, +{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091}, +{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6}, +{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085}, +{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c}, +{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1}, +{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f}, +{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025}, +{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016}, +{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052}, +{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e}, +{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7}, +{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6}, +{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4}, +{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083}, +{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001}, +{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046}, +{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081}, +{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a}, +{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd}, +{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025}, +{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084}, +{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084}, +{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018}, +{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019}, +{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004}, +{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e}, +{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b}, +{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007}, +{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027}, +{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081}, +{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b}, +{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007}, +{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027}, +{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e}, +{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd}, +{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086}, +{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049}, +{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012}, +{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071}, +{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f}, +{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084}, +{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008}, +{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6}, +{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4}, +{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006}, +{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025}, +{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016}, +{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e}, +{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd}, +{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026}, +{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082}, +{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001}, +{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084}, +{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f}, +{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec}, +{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa}, +{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7}, +{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f}, +{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd}, +{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce}, +{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff}, +{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096}, +{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c}, +{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026}, +{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012}, +{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f}, +{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027}, +{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023}, +{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027}, +{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084}, +{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051}, +{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091}, +{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e}, +{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce}, +{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff}, +{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e}, +{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd}, +{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c}, +{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce}, +{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff}, +{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e}, +{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096}, +{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c}, +{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026}, +{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024}, +{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026}, +{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018}, +{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019}, +{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001}, +{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009}, +{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020}, +{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081}, +{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015}, +{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044}, +{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1}, +{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f}, +{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044}, +{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029}, +{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025}, +{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f}, +{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047}, +{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a}, +{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047}, +{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034}, +{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011}, +{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084}, +{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002}, +{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e}, +{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096}, +{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc}, +{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097}, +{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1}, +{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086}, +{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012}, +{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7}, +{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010}, +{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd}, +{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031}, +{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e}, +{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6}, +{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f}, +{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7}, +{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f}, +{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec}, +{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa}, +{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008}, +{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5}, +{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002}, +{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6}, +{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4}, +{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084}, +{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001}, +{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046}, +{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081}, +{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003}, +{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f}, +{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd}, +{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025}, +{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085}, +{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044}, +{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026}, +{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012}, +{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001}, +{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010}, +{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd}, +{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce}, +{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff}, +{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e}, +{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096}, +{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003}, +{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026}, +{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012}, +{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003}, +{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027}, +{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085}, +{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044}, +{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026}, +{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012}, +{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001}, +{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010}, +{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce}, +{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff}, +{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e}, +{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6}, +{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a}, +{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010}, +{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085}, +{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8}, +{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000}, +{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084}, +{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001}, +{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085}, +{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046}, +{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081}, +{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009}, +{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030}, +{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081}, +{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f}, +{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044}, +{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b}, +{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029}, +{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026}, +{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011}, +{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022}, +{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6}, +{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba}, +{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084}, +{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d}, +{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085}, +{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005}, +{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e}, +{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca}, +{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022}, +{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000}, +{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018}, +{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000}, +{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046}, +{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085}, +{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002}, +{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085}, +{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001}, +{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f}, +{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004}, +{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004}, +{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7}, +{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086}, +{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012}, +{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007}, +{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006}, +{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d}, +{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070}, +{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba}, +{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7}, +{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001}, +{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001}, +{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6}, +{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084}, +{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002}, +{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004}, +{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001}, +{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001}, +{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4}, +{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7}, +{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6}, +{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084}, +{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008}, +{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6}, +{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081}, +{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008}, +{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7}, +{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e}, +{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086}, +{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040}, +{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e}, +{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7}, +{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f}, +{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082}, +{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f}, +{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f}, +{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f}, +{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f}, +{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f}, +{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f}, +{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f}, +{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f}, +{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f}, +{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f}, +{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f}, +{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f}, +{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f}, +{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012}, +{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010}, +{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004}, +{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7}, +{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7}, +{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7}, +{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7}, +{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086}, +{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012}, +{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012}, +{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7}, +{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004}, +{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004}, +{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001}, +{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001}, +{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008}, +{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081}, +{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b}, +{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce}, +{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd}, +{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e}, +{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081}, +{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b}, +{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce}, +{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd}, +{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e}, +{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081}, +{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b}, +{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce}, +{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd}, +{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e}, +{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081}, +{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b}, +{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce}, +{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd}, +{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e}, +{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081}, +{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b}, +{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce}, +{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd}, +{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e}, +{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081}, +{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b}, +{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce}, +{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd}, +{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e}, +{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081}, +{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b}, +{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce}, +{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd}, +{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e}, +{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081}, +{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008}, +{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce}, +{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd}, +{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6}, +{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081}, +{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003}, +{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047}, +{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009}, +{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081}, +{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006}, +{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009}, +{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe}, +{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006}, +{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081}, +{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008}, +{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7}, +{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e}, +{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6}, +{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026}, +{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f}, +{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7}, +{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e}, +{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6}, +{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084}, +{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f}, +{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b}, +{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012}, +{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012}, +{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc}, +{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009}, +{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe}, +{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070}, +{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f}, +{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c}, +{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f}, +{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084}, +{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f}, +{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c}, +{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f}, +{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1}, +{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003}, +{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040}, +{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f}, +{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027}, +{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b}, +{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081}, +{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b}, +{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027}, +{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087}, +{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f}, +{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002}, +{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a}, +{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7}, +{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086}, +{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f}, +{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012}, +{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075}, +{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7}, +{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020}, +{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f}, +{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002}, +{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071}, +{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047}, +{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097}, +{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089}, +{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f}, +{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089}, +{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f}, +{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089}, +{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f}, +{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089}, +{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f}, +{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089}, +{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7}, +{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7}, +{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6}, +{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027}, +{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f}, +{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f}, +{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f}, +{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d}, +{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078}, +{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c}, +{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6}, +{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027}, +{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f}, +{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f}, +{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f}, +{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b}, +{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d}, +{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075}, +{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c}, +{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a}, +{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027}, +{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f}, +{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f}, +{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c}, +{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083}, +{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075}, +{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078}, +{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b}, +{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc}, +{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d}, +{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000}, +{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070}, +{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072}, +{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e}, +{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6}, +{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026}, +{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce}, +{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd}, +{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e}, +{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6}, +{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026}, +{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce}, +{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd}, +{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e}, +{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6}, +{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026}, +{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce}, +{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd}, +{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e}, +{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086}, +{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040}, +{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x0000}, +{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075}, +{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e}, +{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012}, +{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8}, +{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012}, +{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f}, +{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007}, +{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048}, +{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6}, +{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4}, +{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7}, +{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6}, +{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081}, +{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf}, +{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005}, +{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b}, +{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005}, +{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6}, +{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd}, +{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086}, +{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f}, +{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089}, +{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002}, +{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077}, +{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094}, +{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6}, +{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd}, +{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce}, +{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6}, +{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001}, +{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081}, +{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003}, +{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066}, +{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8}, +{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084}, +{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b}, +{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079}, +{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008}, +{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e}, +{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6}, +{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a}, +{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012}, +{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012}, +{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb}, +{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7}, +{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6}, +{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036}, +{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c}, +{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7}, +{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086}, +{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012}, +{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012}, +{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001}, +{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001}, +{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe}, +{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004}, +{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004}, +{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba}, +{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7}, +{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086}, +{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012}, +{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012}, +{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7}, +{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6}, +{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084}, +{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008}, +{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c}, +{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026}, +{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076}, +{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e}, +{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e}, +{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6}, +{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081}, +{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c}, +{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7}, +{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d}, +{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb}, +{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004}, +{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7}, +{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce}, +{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6}, +{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081}, +{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005}, +{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6}, +{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6}, +{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084}, +{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012}, +{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083}, +{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c}, +{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000}, +{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006}, +{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b}, +{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083}, +{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041}, +{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e}, +{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7}, +{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086}, +{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f}, +{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012}, +{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f}, +{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c}, +{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7}, +{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086}, +{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a}, +{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012}, +{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009}, +{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c}, +{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d}, +{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c}, +{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e}, +{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027}, +{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020}, +{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e}, +{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c}, +{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba}, +{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7}, +{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6}, +{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048}, +{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d}, +{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021}, +{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004}, +{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7}, +{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd}, +{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f}, +{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000}, +{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000}, +{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008}, +{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5}, +{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c}, +{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba}, +{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7}, +{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6}, +{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084}, +{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001}, +{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006}, +{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7}, +{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036}, +{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7}, +{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032}, +{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026}, +{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f}, +{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089}, +{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001}, +{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1}, +{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c}, +{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027}, +{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f}, +{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005}, +{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080}, +{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080}, +{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7}, +{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6}, +{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005}, +{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f}, +{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f}, +{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4}, +{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b}, +{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007}, +{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f}, +{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000}, +{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000}, +{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000}, +{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6}, +{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6}, +{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7}, +{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001}, +{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018}, +{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018}, +{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7}, +{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6}, +{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007}, +{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4}, +{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054}, +{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7}, +{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a}, +{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039}, +{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084}, +{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022}, +{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7}, +{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6}, +{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7}, +{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6}, +{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4}, +{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f}, +{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072}, +{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072}, +{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071}, +{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027}, +{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001}, +{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081}, +{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024}, +{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070}, +{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096}, +{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080}, +{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064}, +{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070}, +{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096}, +{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010}, +{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064}, +{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070}, +{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096}, +{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020}, +{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064}, +{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070}, +{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096}, +{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040}, +{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074}, +{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074}, +{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078}, +{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6}, +{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085}, +{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af}, +{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4}, +{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6}, +{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081}, +{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036}, +{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026}, +{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022}, +{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044}, +{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022}, +{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020}, +{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081}, +{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d}, +{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084}, +{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044}, +{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022}, +{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020}, +{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081}, +{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f}, +{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084}, +{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044}, +{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6}, +{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f}, +{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022}, +{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c}, +{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006}, +{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed}, +{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007}, +{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9}, +{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006}, +{0x8aca, 0x0039}, { 0x0, 0x0 } +}; +#else +cas_saturn_patch_t cas_saturn_patch[] = { +{0x8200, 0x007e}, {0x8201, 0x0082}, {0x8202, 0x0009}, +{0x8203, 0x0000}, {0x8204, 0x0000}, {0x8205, 0x0000}, +{0x8206, 0x0000}, {0x8207, 0x0000}, {0x8208, 0x0000}, +{0x8209, 0x008e}, {0x820a, 0x008e}, {0x820b, 0x00ff}, +{0x820c, 0x00ce}, {0x820d, 0x0082}, {0x820e, 0x0025}, +{0x820f, 0x00ff}, {0x8210, 0x0001}, {0x8211, 0x000f}, +{0x8212, 0x00ce}, {0x8213, 0x0084}, {0x8214, 0x0026}, +{0x8215, 0x00ff}, {0x8216, 0x0001}, {0x8217, 0x0011}, +{0x8218, 0x00ce}, {0x8219, 0x0085}, {0x821a, 0x003d}, +{0x821b, 0x00df}, {0x821c, 0x00e5}, {0x821d, 0x0086}, +{0x821e, 0x0039}, {0x821f, 0x00b7}, {0x8220, 0x008f}, +{0x8221, 0x00f8}, {0x8222, 0x007e}, {0x8223, 0x00c3}, +{0x8224, 0x00c2}, {0x8225, 0x0096}, {0x8226, 0x0047}, +{0x8227, 0x0084}, {0x8228, 0x00f3}, {0x8229, 0x008a}, +{0x822a, 0x0000}, {0x822b, 0x0097}, {0x822c, 0x0047}, +{0x822d, 0x00ce}, {0x822e, 0x0082}, {0x822f, 0x0033}, +{0x8230, 0x00ff}, {0x8231, 0x0001}, {0x8232, 0x000f}, +{0x8233, 0x0096}, {0x8234, 0x0046}, {0x8235, 0x0084}, +{0x8236, 0x000c}, {0x8237, 0x0081}, {0x8238, 0x0004}, +{0x8239, 0x0027}, {0x823a, 0x000b}, {0x823b, 0x0096}, +{0x823c, 0x0046}, {0x823d, 0x0084}, {0x823e, 0x000c}, +{0x823f, 0x0081}, {0x8240, 0x0008}, {0x8241, 0x0027}, +{0x8242, 0x0057}, {0x8243, 0x007e}, {0x8244, 0x0084}, +{0x8245, 0x0025}, {0x8246, 0x0096}, {0x8247, 0x0047}, +{0x8248, 0x0084}, {0x8249, 0x00f3}, {0x824a, 0x008a}, +{0x824b, 0x0004}, {0x824c, 0x0097}, {0x824d, 0x0047}, +{0x824e, 0x00ce}, {0x824f, 0x0082}, {0x8250, 0x0054}, +{0x8251, 0x00ff}, {0x8252, 0x0001}, {0x8253, 0x000f}, +{0x8254, 0x0096}, {0x8255, 0x0046}, {0x8256, 0x0084}, +{0x8257, 0x000c}, {0x8258, 0x0081}, {0x8259, 0x0004}, +{0x825a, 0x0026}, {0x825b, 0x0038}, {0x825c, 0x00b6}, +{0x825d, 0x0012}, {0x825e, 0x0020}, {0x825f, 0x0084}, +{0x8260, 0x0020}, {0x8261, 0x0026}, {0x8262, 0x0003}, +{0x8263, 0x007e}, {0x8264, 0x0084}, {0x8265, 0x0025}, +{0x8266, 0x0096}, {0x8267, 0x007b}, {0x8268, 0x00d6}, +{0x8269, 0x007c}, {0x826a, 0x00fe}, {0x826b, 0x008f}, +{0x826c, 0x0056}, {0x826d, 0x00bd}, {0x826e, 0x00f7}, +{0x826f, 0x00b6}, {0x8270, 0x00fe}, {0x8271, 0x008f}, +{0x8272, 0x004e}, {0x8273, 0x00bd}, {0x8274, 0x00ec}, +{0x8275, 0x008e}, {0x8276, 0x00bd}, {0x8277, 0x00fa}, +{0x8278, 0x00f7}, {0x8279, 0x00bd}, {0x827a, 0x00f7}, +{0x827b, 0x0028}, {0x827c, 0x00ce}, {0x827d, 0x0082}, +{0x827e, 0x0082}, {0x827f, 0x00ff}, {0x8280, 0x0001}, +{0x8281, 0x000f}, {0x8282, 0x0096}, {0x8283, 0x0046}, +{0x8284, 0x0084}, {0x8285, 0x000c}, {0x8286, 0x0081}, +{0x8287, 0x0004}, {0x8288, 0x0026}, {0x8289, 0x000a}, +{0x828a, 0x00b6}, {0x828b, 0x0012}, {0x828c, 0x0020}, +{0x828d, 0x0084}, {0x828e, 0x0020}, {0x828f, 0x0027}, +{0x8290, 0x00b5}, {0x8291, 0x007e}, {0x8292, 0x0084}, +{0x8293, 0x0025}, {0x8294, 0x00bd}, {0x8295, 0x00f7}, +{0x8296, 0x001f}, {0x8297, 0x007e}, {0x8298, 0x0084}, +{0x8299, 0x001f}, {0x829a, 0x0096}, {0x829b, 0x0047}, +{0x829c, 0x0084}, {0x829d, 0x00f3}, {0x829e, 0x008a}, +{0x829f, 0x0008}, {0x82a0, 0x0097}, {0x82a1, 0x0047}, +{0x82a2, 0x00de}, {0x82a3, 0x00e1}, {0x82a4, 0x00ad}, +{0x82a5, 0x0000}, {0x82a6, 0x00ce}, {0x82a7, 0x0082}, +{0x82a8, 0x00af}, {0x82a9, 0x00ff}, {0x82aa, 0x0001}, +{0x82ab, 0x000f}, {0x82ac, 0x007e}, {0x82ad, 0x0084}, +{0x82ae, 0x0025}, {0x82af, 0x0096}, {0x82b0, 0x0041}, +{0x82b1, 0x0085}, {0x82b2, 0x0010}, {0x82b3, 0x0026}, +{0x82b4, 0x0006}, {0x82b5, 0x0096}, {0x82b6, 0x0023}, +{0x82b7, 0x0085}, {0x82b8, 0x0040}, {0x82b9, 0x0027}, +{0x82ba, 0x0006}, {0x82bb, 0x00bd}, {0x82bc, 0x00ed}, +{0x82bd, 0x0000}, {0x82be, 0x007e}, {0x82bf, 0x0083}, +{0x82c0, 0x00a2}, {0x82c1, 0x00de}, {0x82c2, 0x0042}, +{0x82c3, 0x00bd}, {0x82c4, 0x00eb}, {0x82c5, 0x008e}, +{0x82c6, 0x0096}, {0x82c7, 0x0024}, {0x82c8, 0x0084}, +{0x82c9, 0x0008}, {0x82ca, 0x0027}, {0x82cb, 0x0003}, +{0x82cc, 0x007e}, {0x82cd, 0x0083}, {0x82ce, 0x00df}, +{0x82cf, 0x0096}, {0x82d0, 0x007b}, {0x82d1, 0x00d6}, +{0x82d2, 0x007c}, {0x82d3, 0x00fe}, {0x82d4, 0x008f}, +{0x82d5, 0x0056}, {0x82d6, 0x00bd}, {0x82d7, 0x00f7}, +{0x82d8, 0x00b6}, {0x82d9, 0x00fe}, {0x82da, 0x008f}, +{0x82db, 0x0050}, {0x82dc, 0x00bd}, {0x82dd, 0x00ec}, +{0x82de, 0x008e}, {0x82df, 0x00bd}, {0x82e0, 0x00fa}, +{0x82e1, 0x00f7}, {0x82e2, 0x0086}, {0x82e3, 0x0011}, +{0x82e4, 0x00c6}, {0x82e5, 0x0049}, {0x82e6, 0x00bd}, +{0x82e7, 0x00e4}, {0x82e8, 0x0012}, {0x82e9, 0x00ce}, +{0x82ea, 0x0082}, {0x82eb, 0x00ef}, {0x82ec, 0x00ff}, +{0x82ed, 0x0001}, {0x82ee, 0x000f}, {0x82ef, 0x0096}, +{0x82f0, 0x0046}, {0x82f1, 0x0084}, {0x82f2, 0x000c}, +{0x82f3, 0x0081}, {0x82f4, 0x0000}, {0x82f5, 0x0027}, +{0x82f6, 0x0017}, {0x82f7, 0x00c6}, {0x82f8, 0x0049}, +{0x82f9, 0x00bd}, {0x82fa, 0x00e4}, {0x82fb, 0x0091}, +{0x82fc, 0x0024}, {0x82fd, 0x000d}, {0x82fe, 0x00b6}, +{0x82ff, 0x0012}, {0x8300, 0x0020}, {0x8301, 0x0085}, +{0x8302, 0x0020}, {0x8303, 0x0026}, {0x8304, 0x000c}, +{0x8305, 0x00ce}, {0x8306, 0x0082}, {0x8307, 0x00c1}, +{0x8308, 0x00ff}, {0x8309, 0x0001}, {0x830a, 0x000f}, +{0x830b, 0x007e}, {0x830c, 0x0084}, {0x830d, 0x0025}, +{0x830e, 0x007e}, {0x830f, 0x0084}, {0x8310, 0x0016}, +{0x8311, 0x00fe}, {0x8312, 0x008f}, {0x8313, 0x0052}, +{0x8314, 0x00bd}, {0x8315, 0x00ec}, {0x8316, 0x008e}, +{0x8317, 0x00bd}, {0x8318, 0x00fa}, {0x8319, 0x00f7}, +{0x831a, 0x0086}, {0x831b, 0x006a}, {0x831c, 0x00c6}, +{0x831d, 0x0049}, {0x831e, 0x00bd}, {0x831f, 0x00e4}, +{0x8320, 0x0012}, {0x8321, 0x00ce}, {0x8322, 0x0083}, +{0x8323, 0x0027}, {0x8324, 0x00ff}, {0x8325, 0x0001}, +{0x8326, 0x000f}, {0x8327, 0x0096}, {0x8328, 0x0046}, +{0x8329, 0x0084}, {0x832a, 0x000c}, {0x832b, 0x0081}, +{0x832c, 0x0000}, {0x832d, 0x0027}, {0x832e, 0x000a}, +{0x832f, 0x00c6}, {0x8330, 0x0049}, {0x8331, 0x00bd}, +{0x8332, 0x00e4}, {0x8333, 0x0091}, {0x8334, 0x0025}, +{0x8335, 0x0006}, {0x8336, 0x007e}, {0x8337, 0x0084}, +{0x8338, 0x0025}, {0x8339, 0x007e}, {0x833a, 0x0084}, +{0x833b, 0x0016}, {0x833c, 0x00b6}, {0x833d, 0x0018}, +{0x833e, 0x0070}, {0x833f, 0x00bb}, {0x8340, 0x0019}, +{0x8341, 0x0070}, {0x8342, 0x002a}, {0x8343, 0x0004}, +{0x8344, 0x0081}, {0x8345, 0x00af}, {0x8346, 0x002e}, +{0x8347, 0x0019}, {0x8348, 0x0096}, {0x8349, 0x007b}, +{0x834a, 0x00f6}, {0x834b, 0x0020}, {0x834c, 0x0007}, +{0x834d, 0x00fa}, {0x834e, 0x0020}, {0x834f, 0x0027}, +{0x8350, 0x00c4}, {0x8351, 0x0038}, {0x8352, 0x0081}, +{0x8353, 0x0038}, {0x8354, 0x0027}, {0x8355, 0x000b}, +{0x8356, 0x00f6}, {0x8357, 0x0020}, {0x8358, 0x0007}, +{0x8359, 0x00fa}, {0x835a, 0x0020}, {0x835b, 0x0027}, +{0x835c, 0x00cb}, {0x835d, 0x0008}, {0x835e, 0x007e}, +{0x835f, 0x0082}, {0x8360, 0x00d3}, {0x8361, 0x00bd}, +{0x8362, 0x00f7}, {0x8363, 0x0066}, {0x8364, 0x0086}, +{0x8365, 0x0074}, {0x8366, 0x00c6}, {0x8367, 0x0049}, +{0x8368, 0x00bd}, {0x8369, 0x00e4}, {0x836a, 0x0012}, +{0x836b, 0x00ce}, {0x836c, 0x0083}, {0x836d, 0x0071}, +{0x836e, 0x00ff}, {0x836f, 0x0001}, {0x8370, 0x000f}, +{0x8371, 0x0096}, {0x8372, 0x0046}, {0x8373, 0x0084}, +{0x8374, 0x000c}, {0x8375, 0x0081}, {0x8376, 0x0008}, +{0x8377, 0x0026}, {0x8378, 0x000a}, {0x8379, 0x00c6}, +{0x837a, 0x0049}, {0x837b, 0x00bd}, {0x837c, 0x00e4}, +{0x837d, 0x0091}, {0x837e, 0x0025}, {0x837f, 0x0006}, +{0x8380, 0x007e}, {0x8381, 0x0084}, {0x8382, 0x0025}, +{0x8383, 0x007e}, {0x8384, 0x0084}, {0x8385, 0x0016}, +{0x8386, 0x00bd}, {0x8387, 0x00f7}, {0x8388, 0x003e}, +{0x8389, 0x0026}, {0x838a, 0x000e}, {0x838b, 0x00bd}, +{0x838c, 0x00e5}, {0x838d, 0x0009}, {0x838e, 0x0026}, +{0x838f, 0x0006}, {0x8390, 0x00ce}, {0x8391, 0x0082}, +{0x8392, 0x00c1}, {0x8393, 0x00ff}, {0x8394, 0x0001}, +{0x8395, 0x000f}, {0x8396, 0x007e}, {0x8397, 0x0084}, +{0x8398, 0x0025}, {0x8399, 0x00fe}, {0x839a, 0x008f}, +{0x839b, 0x0054}, {0x839c, 0x00bd}, {0x839d, 0x00ec}, +{0x839e, 0x008e}, {0x839f, 0x00bd}, {0x83a0, 0x00fa}, +{0x83a1, 0x00f7}, {0x83a2, 0x00bd}, {0x83a3, 0x00f7}, +{0x83a4, 0x0033}, {0x83a5, 0x0086}, {0x83a6, 0x000f}, +{0x83a7, 0x00c6}, {0x83a8, 0x0051}, {0x83a9, 0x00bd}, +{0x83aa, 0x00e4}, {0x83ab, 0x0012}, {0x83ac, 0x00ce}, +{0x83ad, 0x0083}, {0x83ae, 0x00b2}, {0x83af, 0x00ff}, +{0x83b0, 0x0001}, {0x83b1, 0x000f}, {0x83b2, 0x0096}, +{0x83b3, 0x0046}, {0x83b4, 0x0084}, {0x83b5, 0x000c}, +{0x83b6, 0x0081}, {0x83b7, 0x0008}, {0x83b8, 0x0026}, +{0x83b9, 0x005c}, {0x83ba, 0x00b6}, {0x83bb, 0x0012}, +{0x83bc, 0x0020}, {0x83bd, 0x0084}, {0x83be, 0x003f}, +{0x83bf, 0x0081}, {0x83c0, 0x003a}, {0x83c1, 0x0027}, +{0x83c2, 0x001c}, {0x83c3, 0x0096}, {0x83c4, 0x0023}, +{0x83c5, 0x0085}, {0x83c6, 0x0040}, {0x83c7, 0x0027}, +{0x83c8, 0x0003}, {0x83c9, 0x007e}, {0x83ca, 0x0084}, +{0x83cb, 0x0025}, {0x83cc, 0x00c6}, {0x83cd, 0x0051}, +{0x83ce, 0x00bd}, {0x83cf, 0x00e4}, {0x83d0, 0x0091}, +{0x83d1, 0x0025}, {0x83d2, 0x0003}, {0x83d3, 0x007e}, +{0x83d4, 0x0084}, {0x83d5, 0x0025}, {0x83d6, 0x00ce}, +{0x83d7, 0x0082}, {0x83d8, 0x00c1}, {0x83d9, 0x00ff}, +{0x83da, 0x0001}, {0x83db, 0x000f}, {0x83dc, 0x007e}, +{0x83dd, 0x0084}, {0x83de, 0x0025}, {0x83df, 0x00bd}, +{0x83e0, 0x00f8}, {0x83e1, 0x0037}, {0x83e2, 0x007c}, +{0x83e3, 0x0000}, {0x83e4, 0x007a}, {0x83e5, 0x00ce}, +{0x83e6, 0x0083}, {0x83e7, 0x00ee}, {0x83e8, 0x00ff}, +{0x83e9, 0x0001}, {0x83ea, 0x000f}, {0x83eb, 0x007e}, +{0x83ec, 0x0084}, {0x83ed, 0x0025}, {0x83ee, 0x0096}, +{0x83ef, 0x0046}, {0x83f0, 0x0084}, {0x83f1, 0x000c}, +{0x83f2, 0x0081}, {0x83f3, 0x0008}, {0x83f4, 0x0026}, +{0x83f5, 0x0020}, {0x83f6, 0x0096}, {0x83f7, 0x0024}, +{0x83f8, 0x0084}, {0x83f9, 0x0008}, {0x83fa, 0x0026}, +{0x83fb, 0x0029}, {0x83fc, 0x00b6}, {0x83fd, 0x0018}, +{0x83fe, 0x0082}, {0x83ff, 0x00bb}, {0x8400, 0x0019}, +{0x8401, 0x0082}, {0x8402, 0x00b1}, {0x8403, 0x0001}, +{0x8404, 0x003b}, {0x8405, 0x0022}, {0x8406, 0x0009}, +{0x8407, 0x00b6}, {0x8408, 0x0012}, {0x8409, 0x0020}, +{0x840a, 0x0084}, {0x840b, 0x0037}, {0x840c, 0x0081}, +{0x840d, 0x0032}, {0x840e, 0x0027}, {0x840f, 0x0015}, +{0x8410, 0x00bd}, {0x8411, 0x00f8}, {0x8412, 0x0044}, +{0x8413, 0x007e}, {0x8414, 0x0082}, {0x8415, 0x00c1}, +{0x8416, 0x00bd}, {0x8417, 0x00f7}, {0x8418, 0x001f}, +{0x8419, 0x00bd}, {0x841a, 0x00f8}, {0x841b, 0x0044}, +{0x841c, 0x00bd}, {0x841d, 0x00fc}, {0x841e, 0x0029}, +{0x841f, 0x00ce}, {0x8420, 0x0082}, {0x8421, 0x0025}, +{0x8422, 0x00ff}, {0x8423, 0x0001}, {0x8424, 0x000f}, +{0x8425, 0x0039}, {0x8426, 0x0096}, {0x8427, 0x0047}, +{0x8428, 0x0084}, {0x8429, 0x00fc}, {0x842a, 0x008a}, +{0x842b, 0x0000}, {0x842c, 0x0097}, {0x842d, 0x0047}, +{0x842e, 0x00ce}, {0x842f, 0x0084}, {0x8430, 0x0034}, +{0x8431, 0x00ff}, {0x8432, 0x0001}, {0x8433, 0x0011}, +{0x8434, 0x0096}, {0x8435, 0x0046}, {0x8436, 0x0084}, +{0x8437, 0x0003}, {0x8438, 0x0081}, {0x8439, 0x0002}, +{0x843a, 0x0027}, {0x843b, 0x0003}, {0x843c, 0x007e}, +{0x843d, 0x0085}, {0x843e, 0x001e}, {0x843f, 0x0096}, +{0x8440, 0x0047}, {0x8441, 0x0084}, {0x8442, 0x00fc}, +{0x8443, 0x008a}, {0x8444, 0x0002}, {0x8445, 0x0097}, +{0x8446, 0x0047}, {0x8447, 0x00de}, {0x8448, 0x00e1}, +{0x8449, 0x00ad}, {0x844a, 0x0000}, {0x844b, 0x0086}, +{0x844c, 0x0001}, {0x844d, 0x00b7}, {0x844e, 0x0012}, +{0x844f, 0x0051}, {0x8450, 0x00bd}, {0x8451, 0x00f7}, +{0x8452, 0x0014}, {0x8453, 0x00b6}, {0x8454, 0x0010}, +{0x8455, 0x0031}, {0x8456, 0x0084}, {0x8457, 0x00fd}, +{0x8458, 0x00b7}, {0x8459, 0x0010}, {0x845a, 0x0031}, +{0x845b, 0x00bd}, {0x845c, 0x00f8}, {0x845d, 0x001e}, +{0x845e, 0x0096}, {0x845f, 0x0081}, {0x8460, 0x00d6}, +{0x8461, 0x0082}, {0x8462, 0x00fe}, {0x8463, 0x008f}, +{0x8464, 0x005a}, {0x8465, 0x00bd}, {0x8466, 0x00f7}, +{0x8467, 0x00b6}, {0x8468, 0x00fe}, {0x8469, 0x008f}, +{0x846a, 0x005c}, {0x846b, 0x00bd}, {0x846c, 0x00ec}, +{0x846d, 0x008e}, {0x846e, 0x00bd}, {0x846f, 0x00fa}, +{0x8470, 0x00f7}, {0x8471, 0x0086}, {0x8472, 0x0008}, +{0x8473, 0x00d6}, {0x8474, 0x0000}, {0x8475, 0x00c5}, +{0x8476, 0x0010}, {0x8477, 0x0026}, {0x8478, 0x0002}, +{0x8479, 0x008b}, {0x847a, 0x0020}, {0x847b, 0x00c6}, +{0x847c, 0x0051}, {0x847d, 0x00bd}, {0x847e, 0x00e4}, +{0x847f, 0x0012}, {0x8480, 0x00ce}, {0x8481, 0x0084}, +{0x8482, 0x0086}, {0x8483, 0x00ff}, {0x8484, 0x0001}, +{0x8485, 0x0011}, {0x8486, 0x0096}, {0x8487, 0x0046}, +{0x8488, 0x0084}, {0x8489, 0x0003}, {0x848a, 0x0081}, +{0x848b, 0x0002}, {0x848c, 0x0027}, {0x848d, 0x0003}, +{0x848e, 0x007e}, {0x848f, 0x0085}, {0x8490, 0x000f}, +{0x8491, 0x00c6}, {0x8492, 0x0051}, {0x8493, 0x00bd}, +{0x8494, 0x00e4}, {0x8495, 0x0091}, {0x8496, 0x0025}, +{0x8497, 0x0003}, {0x8498, 0x007e}, {0x8499, 0x0085}, +{0x849a, 0x001e}, {0x849b, 0x0096}, {0x849c, 0x0044}, +{0x849d, 0x0085}, {0x849e, 0x0010}, {0x849f, 0x0026}, +{0x84a0, 0x000a}, {0x84a1, 0x00b6}, {0x84a2, 0x0012}, +{0x84a3, 0x0050}, {0x84a4, 0x00ba}, {0x84a5, 0x0001}, +{0x84a6, 0x003c}, {0x84a7, 0x0085}, {0x84a8, 0x0010}, +{0x84a9, 0x0027}, {0x84aa, 0x00a8}, {0x84ab, 0x00bd}, +{0x84ac, 0x00f7}, {0x84ad, 0x0066}, {0x84ae, 0x00ce}, +{0x84af, 0x0084}, {0x84b0, 0x00b7}, {0x84b1, 0x00ff}, +{0x84b2, 0x0001}, {0x84b3, 0x0011}, {0x84b4, 0x007e}, +{0x84b5, 0x0085}, {0x84b6, 0x001e}, {0x84b7, 0x0096}, +{0x84b8, 0x0046}, {0x84b9, 0x0084}, {0x84ba, 0x0003}, +{0x84bb, 0x0081}, {0x84bc, 0x0002}, {0x84bd, 0x0026}, +{0x84be, 0x0050}, {0x84bf, 0x00b6}, {0x84c0, 0x0012}, +{0x84c1, 0x0030}, {0x84c2, 0x0084}, {0x84c3, 0x0003}, +{0x84c4, 0x0081}, {0x84c5, 0x0001}, {0x84c6, 0x0027}, +{0x84c7, 0x0003}, {0x84c8, 0x007e}, {0x84c9, 0x0085}, +{0x84ca, 0x001e}, {0x84cb, 0x0096}, {0x84cc, 0x0044}, +{0x84cd, 0x0085}, {0x84ce, 0x0010}, {0x84cf, 0x0026}, +{0x84d0, 0x0013}, {0x84d1, 0x00b6}, {0x84d2, 0x0012}, +{0x84d3, 0x0050}, {0x84d4, 0x00ba}, {0x84d5, 0x0001}, +{0x84d6, 0x003c}, {0x84d7, 0x0085}, {0x84d8, 0x0010}, +{0x84d9, 0x0026}, {0x84da, 0x0009}, {0x84db, 0x00ce}, +{0x84dc, 0x0084}, {0x84dd, 0x0053}, {0x84de, 0x00ff}, +{0x84df, 0x0001}, {0x84e0, 0x0011}, {0x84e1, 0x007e}, +{0x84e2, 0x0085}, {0x84e3, 0x001e}, {0x84e4, 0x00b6}, +{0x84e5, 0x0010}, {0x84e6, 0x0031}, {0x84e7, 0x008a}, +{0x84e8, 0x0002}, {0x84e9, 0x00b7}, {0x84ea, 0x0010}, +{0x84eb, 0x0031}, {0x84ec, 0x00bd}, {0x84ed, 0x0085}, +{0x84ee, 0x001f}, {0x84ef, 0x00bd}, {0x84f0, 0x00f8}, +{0x84f1, 0x0037}, {0x84f2, 0x007c}, {0x84f3, 0x0000}, +{0x84f4, 0x0080}, {0x84f5, 0x00ce}, {0x84f6, 0x0084}, +{0x84f7, 0x00fe}, {0x84f8, 0x00ff}, {0x84f9, 0x0001}, +{0x84fa, 0x0011}, {0x84fb, 0x007e}, {0x84fc, 0x0085}, +{0x84fd, 0x001e}, {0x84fe, 0x0096}, {0x84ff, 0x0046}, +{0x8500, 0x0084}, {0x8501, 0x0003}, {0x8502, 0x0081}, +{0x8503, 0x0002}, {0x8504, 0x0026}, {0x8505, 0x0009}, +{0x8506, 0x00b6}, {0x8507, 0x0012}, {0x8508, 0x0030}, +{0x8509, 0x0084}, {0x850a, 0x0003}, {0x850b, 0x0081}, +{0x850c, 0x0001}, {0x850d, 0x0027}, {0x850e, 0x000f}, +{0x850f, 0x00bd}, {0x8510, 0x00f8}, {0x8511, 0x0044}, +{0x8512, 0x00bd}, {0x8513, 0x00f7}, {0x8514, 0x000b}, +{0x8515, 0x00bd}, {0x8516, 0x00fc}, {0x8517, 0x0029}, +{0x8518, 0x00ce}, {0x8519, 0x0084}, {0x851a, 0x0026}, +{0x851b, 0x00ff}, {0x851c, 0x0001}, {0x851d, 0x0011}, +{0x851e, 0x0039}, {0x851f, 0x00d6}, {0x8520, 0x0022}, +{0x8521, 0x00c4}, {0x8522, 0x000f}, {0x8523, 0x00b6}, +{0x8524, 0x0012}, {0x8525, 0x0030}, {0x8526, 0x00ba}, +{0x8527, 0x0012}, {0x8528, 0x0032}, {0x8529, 0x0084}, +{0x852a, 0x0004}, {0x852b, 0x0027}, {0x852c, 0x000d}, +{0x852d, 0x0096}, {0x852e, 0x0022}, {0x852f, 0x0085}, +{0x8530, 0x0004}, {0x8531, 0x0027}, {0x8532, 0x0005}, +{0x8533, 0x00ca}, {0x8534, 0x0010}, {0x8535, 0x007e}, +{0x8536, 0x0085}, {0x8537, 0x003a}, {0x8538, 0x00ca}, +{0x8539, 0x0020}, {0x853a, 0x00d7}, {0x853b, 0x0022}, +{0x853c, 0x0039}, {0x853d, 0x0086}, {0x853e, 0x0000}, +{0x853f, 0x0097}, {0x8540, 0x0083}, {0x8541, 0x0018}, +{0x8542, 0x00ce}, {0x8543, 0x001c}, {0x8544, 0x0000}, +{0x8545, 0x00bd}, {0x8546, 0x00eb}, {0x8547, 0x0046}, +{0x8548, 0x0096}, {0x8549, 0x0057}, {0x854a, 0x0085}, +{0x854b, 0x0001}, {0x854c, 0x0027}, {0x854d, 0x0002}, +{0x854e, 0x004f}, {0x854f, 0x0039}, {0x8550, 0x0085}, +{0x8551, 0x0002}, {0x8552, 0x0027}, {0x8553, 0x0001}, +{0x8554, 0x0039}, {0x8555, 0x007f}, {0x8556, 0x008f}, +{0x8557, 0x007d}, {0x8558, 0x0086}, {0x8559, 0x0004}, +{0x855a, 0x00b7}, {0x855b, 0x0012}, {0x855c, 0x0004}, +{0x855d, 0x0086}, {0x855e, 0x0008}, {0x855f, 0x00b7}, +{0x8560, 0x0012}, {0x8561, 0x0007}, {0x8562, 0x0086}, +{0x8563, 0x0010}, {0x8564, 0x00b7}, {0x8565, 0x0012}, +{0x8566, 0x000c}, {0x8567, 0x0086}, {0x8568, 0x0007}, +{0x8569, 0x00b7}, {0x856a, 0x0012}, {0x856b, 0x0006}, +{0x856c, 0x00b6}, {0x856d, 0x008f}, {0x856e, 0x007d}, +{0x856f, 0x00b7}, {0x8570, 0x0012}, {0x8571, 0x0070}, +{0x8572, 0x0086}, {0x8573, 0x0001}, {0x8574, 0x00ba}, +{0x8575, 0x0012}, {0x8576, 0x0004}, {0x8577, 0x00b7}, +{0x8578, 0x0012}, {0x8579, 0x0004}, {0x857a, 0x0001}, +{0x857b, 0x0001}, {0x857c, 0x0001}, {0x857d, 0x0001}, +{0x857e, 0x0001}, {0x857f, 0x0001}, {0x8580, 0x00b6}, +{0x8581, 0x0012}, {0x8582, 0x0004}, {0x8583, 0x0084}, +{0x8584, 0x00fe}, {0x8585, 0x008a}, {0x8586, 0x0002}, +{0x8587, 0x00b7}, {0x8588, 0x0012}, {0x8589, 0x0004}, +{0x858a, 0x0001}, {0x858b, 0x0001}, {0x858c, 0x0001}, +{0x858d, 0x0001}, {0x858e, 0x0001}, {0x858f, 0x0001}, +{0x8590, 0x0086}, {0x8591, 0x00fd}, {0x8592, 0x00b4}, +{0x8593, 0x0012}, {0x8594, 0x0004}, {0x8595, 0x00b7}, +{0x8596, 0x0012}, {0x8597, 0x0004}, {0x8598, 0x00b6}, +{0x8599, 0x0012}, {0x859a, 0x0000}, {0x859b, 0x0084}, +{0x859c, 0x0008}, {0x859d, 0x0081}, {0x859e, 0x0008}, +{0x859f, 0x0027}, {0x85a0, 0x0016}, {0x85a1, 0x00b6}, +{0x85a2, 0x008f}, {0x85a3, 0x007d}, {0x85a4, 0x0081}, +{0x85a5, 0x000c}, {0x85a6, 0x0027}, {0x85a7, 0x0008}, +{0x85a8, 0x008b}, {0x85a9, 0x0004}, {0x85aa, 0x00b7}, +{0x85ab, 0x008f}, {0x85ac, 0x007d}, {0x85ad, 0x007e}, +{0x85ae, 0x0085}, {0x85af, 0x006c}, {0x85b0, 0x0086}, +{0x85b1, 0x0003}, {0x85b2, 0x0097}, {0x85b3, 0x0040}, +{0x85b4, 0x007e}, {0x85b5, 0x0089}, {0x85b6, 0x006e}, +{0x85b7, 0x0086}, {0x85b8, 0x0007}, {0x85b9, 0x00b7}, +{0x85ba, 0x0012}, {0x85bb, 0x0006}, {0x85bc, 0x005f}, +{0x85bd, 0x00f7}, {0x85be, 0x008f}, {0x85bf, 0x0082}, +{0x85c0, 0x005f}, {0x85c1, 0x00f7}, {0x85c2, 0x008f}, +{0x85c3, 0x007f}, {0x85c4, 0x00f7}, {0x85c5, 0x008f}, +{0x85c6, 0x0070}, {0x85c7, 0x00f7}, {0x85c8, 0x008f}, +{0x85c9, 0x0071}, {0x85ca, 0x00f7}, {0x85cb, 0x008f}, +{0x85cc, 0x0072}, {0x85cd, 0x00f7}, {0x85ce, 0x008f}, +{0x85cf, 0x0073}, {0x85d0, 0x00f7}, {0x85d1, 0x008f}, +{0x85d2, 0x0074}, {0x85d3, 0x00f7}, {0x85d4, 0x008f}, +{0x85d5, 0x0075}, {0x85d6, 0x00f7}, {0x85d7, 0x008f}, +{0x85d8, 0x0076}, {0x85d9, 0x00f7}, {0x85da, 0x008f}, +{0x85db, 0x0077}, {0x85dc, 0x00f7}, {0x85dd, 0x008f}, +{0x85de, 0x0078}, {0x85df, 0x00f7}, {0x85e0, 0x008f}, +{0x85e1, 0x0079}, {0x85e2, 0x00f7}, {0x85e3, 0x008f}, +{0x85e4, 0x007a}, {0x85e5, 0x00f7}, {0x85e6, 0x008f}, +{0x85e7, 0x007b}, {0x85e8, 0x00b6}, {0x85e9, 0x0012}, +{0x85ea, 0x0004}, {0x85eb, 0x008a}, {0x85ec, 0x0010}, +{0x85ed, 0x00b7}, {0x85ee, 0x0012}, {0x85ef, 0x0004}, +{0x85f0, 0x0086}, {0x85f1, 0x00e4}, {0x85f2, 0x00b7}, +{0x85f3, 0x0012}, {0x85f4, 0x0070}, {0x85f5, 0x00b7}, +{0x85f6, 0x0012}, {0x85f7, 0x0007}, {0x85f8, 0x00f7}, +{0x85f9, 0x0012}, {0x85fa, 0x0005}, {0x85fb, 0x00f7}, +{0x85fc, 0x0012}, {0x85fd, 0x0009}, {0x85fe, 0x0086}, +{0x85ff, 0x0008}, {0x8600, 0x00ba}, {0x8601, 0x0012}, +{0x8602, 0x0004}, {0x8603, 0x00b7}, {0x8604, 0x0012}, +{0x8605, 0x0004}, {0x8606, 0x0086}, {0x8607, 0x00f7}, +{0x8608, 0x00b4}, {0x8609, 0x0012}, {0x860a, 0x0004}, +{0x860b, 0x00b7}, {0x860c, 0x0012}, {0x860d, 0x0004}, +{0x860e, 0x0001}, {0x860f, 0x0001}, {0x8610, 0x0001}, +{0x8611, 0x0001}, {0x8612, 0x0001}, {0x8613, 0x0001}, +{0x8614, 0x00b6}, {0x8615, 0x0012}, {0x8616, 0x0008}, +{0x8617, 0x0027}, {0x8618, 0x007f}, {0x8619, 0x0081}, +{0x861a, 0x0080}, {0x861b, 0x0026}, {0x861c, 0x000b}, +{0x861d, 0x0086}, {0x861e, 0x0008}, {0x861f, 0x00ce}, +{0x8620, 0x008f}, {0x8621, 0x0079}, {0x8622, 0x00bd}, +{0x8623, 0x0089}, {0x8624, 0x007b}, {0x8625, 0x007e}, +{0x8626, 0x0086}, {0x8627, 0x008e}, {0x8628, 0x0081}, +{0x8629, 0x0040}, {0x862a, 0x0026}, {0x862b, 0x000b}, +{0x862c, 0x0086}, {0x862d, 0x0004}, {0x862e, 0x00ce}, +{0x862f, 0x008f}, {0x8630, 0x0076}, {0x8631, 0x00bd}, +{0x8632, 0x0089}, {0x8633, 0x007b}, {0x8634, 0x007e}, +{0x8635, 0x0086}, {0x8636, 0x008e}, {0x8637, 0x0081}, +{0x8638, 0x0020}, {0x8639, 0x0026}, {0x863a, 0x000b}, +{0x863b, 0x0086}, {0x863c, 0x0002}, {0x863d, 0x00ce}, +{0x863e, 0x008f}, {0x863f, 0x0073}, {0x8640, 0x00bd}, +{0x8641, 0x0089}, {0x8642, 0x007b}, {0x8643, 0x007e}, +{0x8644, 0x0086}, {0x8645, 0x008e}, {0x8646, 0x0081}, +{0x8647, 0x0010}, {0x8648, 0x0026}, {0x8649, 0x000b}, +{0x864a, 0x0086}, {0x864b, 0x0001}, {0x864c, 0x00ce}, +{0x864d, 0x008f}, {0x864e, 0x0070}, {0x864f, 0x00bd}, +{0x8650, 0x0089}, {0x8651, 0x007b}, {0x8652, 0x007e}, +{0x8653, 0x0086}, {0x8654, 0x008e}, {0x8655, 0x0081}, +{0x8656, 0x0008}, {0x8657, 0x0026}, {0x8658, 0x000b}, +{0x8659, 0x0086}, {0x865a, 0x0008}, {0x865b, 0x00ce}, +{0x865c, 0x008f}, {0x865d, 0x0079}, {0x865e, 0x00bd}, +{0x865f, 0x0089}, {0x8660, 0x007f}, {0x8661, 0x007e}, +{0x8662, 0x0086}, {0x8663, 0x008e}, {0x8664, 0x0081}, +{0x8665, 0x0004}, {0x8666, 0x0026}, {0x8667, 0x000b}, +{0x8668, 0x0086}, {0x8669, 0x0004}, {0x866a, 0x00ce}, +{0x866b, 0x008f}, {0x866c, 0x0076}, {0x866d, 0x00bd}, +{0x866e, 0x0089}, {0x866f, 0x007f}, {0x8670, 0x007e}, +{0x8671, 0x0086}, {0x8672, 0x008e}, {0x8673, 0x0081}, +{0x8674, 0x0002}, {0x8675, 0x0026}, {0x8676, 0x000b}, +{0x8677, 0x008a}, {0x8678, 0x0002}, {0x8679, 0x00ce}, +{0x867a, 0x008f}, {0x867b, 0x0073}, {0x867c, 0x00bd}, +{0x867d, 0x0089}, {0x867e, 0x007f}, {0x867f, 0x007e}, +{0x8680, 0x0086}, {0x8681, 0x008e}, {0x8682, 0x0081}, +{0x8683, 0x0001}, {0x8684, 0x0026}, {0x8685, 0x0008}, +{0x8686, 0x0086}, {0x8687, 0x0001}, {0x8688, 0x00ce}, +{0x8689, 0x008f}, {0x868a, 0x0070}, {0x868b, 0x00bd}, +{0x868c, 0x0089}, {0x868d, 0x007f}, {0x868e, 0x00b6}, +{0x868f, 0x008f}, {0x8690, 0x007f}, {0x8691, 0x0081}, +{0x8692, 0x000f}, {0x8693, 0x0026}, {0x8694, 0x0003}, +{0x8695, 0x007e}, {0x8696, 0x0087}, {0x8697, 0x0047}, +{0x8698, 0x00b6}, {0x8699, 0x0012}, {0x869a, 0x0009}, +{0x869b, 0x0084}, {0x869c, 0x0003}, {0x869d, 0x0081}, +{0x869e, 0x0003}, {0x869f, 0x0027}, {0x86a0, 0x0006}, +{0x86a1, 0x007c}, {0x86a2, 0x0012}, {0x86a3, 0x0009}, +{0x86a4, 0x007e}, {0x86a5, 0x0085}, {0x86a6, 0x00fe}, +{0x86a7, 0x00b6}, {0x86a8, 0x0012}, {0x86a9, 0x0006}, +{0x86aa, 0x0084}, {0x86ab, 0x0007}, {0x86ac, 0x0081}, +{0x86ad, 0x0007}, {0x86ae, 0x0027}, {0x86af, 0x0008}, +{0x86b0, 0x008b}, {0x86b1, 0x0001}, {0x86b2, 0x00b7}, +{0x86b3, 0x0012}, {0x86b4, 0x0006}, {0x86b5, 0x007e}, +{0x86b6, 0x0086}, {0x86b7, 0x00d5}, {0x86b8, 0x00b6}, +{0x86b9, 0x008f}, {0x86ba, 0x0082}, {0x86bb, 0x0026}, +{0x86bc, 0x000a}, {0x86bd, 0x007c}, {0x86be, 0x008f}, +{0x86bf, 0x0082}, {0x86c0, 0x004f}, {0x86c1, 0x00b7}, +{0x86c2, 0x0012}, {0x86c3, 0x0006}, {0x86c4, 0x007e}, +{0x86c5, 0x0085}, {0x86c6, 0x00c0}, {0x86c7, 0x00b6}, +{0x86c8, 0x0012}, {0x86c9, 0x0006}, {0x86ca, 0x0084}, +{0x86cb, 0x003f}, {0x86cc, 0x0081}, {0x86cd, 0x003f}, +{0x86ce, 0x0027}, {0x86cf, 0x0010}, {0x86d0, 0x008b}, +{0x86d1, 0x0008}, {0x86d2, 0x00b7}, {0x86d3, 0x0012}, +{0x86d4, 0x0006}, {0x86d5, 0x00b6}, {0x86d6, 0x0012}, +{0x86d7, 0x0009}, {0x86d8, 0x0084}, {0x86d9, 0x00fc}, +{0x86da, 0x00b7}, {0x86db, 0x0012}, {0x86dc, 0x0009}, +{0x86dd, 0x007e}, {0x86de, 0x0085}, {0x86df, 0x00fe}, +{0x86e0, 0x00ce}, {0x86e1, 0x008f}, {0x86e2, 0x0070}, +{0x86e3, 0x0018}, {0x86e4, 0x00ce}, {0x86e5, 0x008f}, +{0x86e6, 0x0084}, {0x86e7, 0x00c6}, {0x86e8, 0x000c}, +{0x86e9, 0x00bd}, {0x86ea, 0x0089}, {0x86eb, 0x006f}, +{0x86ec, 0x00ce}, {0x86ed, 0x008f}, {0x86ee, 0x0084}, +{0x86ef, 0x0018}, {0x86f0, 0x00ce}, {0x86f1, 0x008f}, +{0x86f2, 0x0070}, {0x86f3, 0x00c6}, {0x86f4, 0x000c}, +{0x86f5, 0x00bd}, {0x86f6, 0x0089}, {0x86f7, 0x006f}, +{0x86f8, 0x00d6}, {0x86f9, 0x0083}, {0x86fa, 0x00c1}, +{0x86fb, 0x004f}, {0x86fc, 0x002d}, {0x86fd, 0x0003}, +{0x86fe, 0x007e}, {0x86ff, 0x0087}, {0x8700, 0x0040}, +{0x8701, 0x00b6}, {0x8702, 0x008f}, {0x8703, 0x007f}, +{0x8704, 0x0081}, {0x8705, 0x0007}, {0x8706, 0x0027}, +{0x8707, 0x000f}, {0x8708, 0x0081}, {0x8709, 0x000b}, +{0x870a, 0x0027}, {0x870b, 0x0015}, {0x870c, 0x0081}, +{0x870d, 0x000d}, {0x870e, 0x0027}, {0x870f, 0x001b}, +{0x8710, 0x0081}, {0x8711, 0x000e}, {0x8712, 0x0027}, +{0x8713, 0x0021}, {0x8714, 0x007e}, {0x8715, 0x0087}, +{0x8716, 0x0040}, {0x8717, 0x00f7}, {0x8718, 0x008f}, +{0x8719, 0x007b}, {0x871a, 0x0086}, {0x871b, 0x0002}, +{0x871c, 0x00b7}, {0x871d, 0x008f}, {0x871e, 0x007a}, +{0x871f, 0x0020}, {0x8720, 0x001c}, {0x8721, 0x00f7}, +{0x8722, 0x008f}, {0x8723, 0x0078}, {0x8724, 0x0086}, +{0x8725, 0x0002}, {0x8726, 0x00b7}, {0x8727, 0x008f}, +{0x8728, 0x0077}, {0x8729, 0x0020}, {0x872a, 0x0012}, +{0x872b, 0x00f7}, {0x872c, 0x008f}, {0x872d, 0x0075}, +{0x872e, 0x0086}, {0x872f, 0x0002}, {0x8730, 0x00b7}, +{0x8731, 0x008f}, {0x8732, 0x0074}, {0x8733, 0x0020}, +{0x8734, 0x0008}, {0x8735, 0x00f7}, {0x8736, 0x008f}, +{0x8737, 0x0072}, {0x8738, 0x0086}, {0x8739, 0x0002}, +{0x873a, 0x00b7}, {0x873b, 0x008f}, {0x873c, 0x0071}, +{0x873d, 0x007e}, {0x873e, 0x0087}, {0x873f, 0x0047}, +{0x8740, 0x0086}, {0x8741, 0x0004}, {0x8742, 0x0097}, +{0x8743, 0x0040}, {0x8744, 0x007e}, {0x8745, 0x0089}, +{0x8746, 0x006e}, {0x8747, 0x00ce}, {0x8748, 0x008f}, +{0x8749, 0x0072}, {0x874a, 0x00bd}, {0x874b, 0x0089}, +{0x874c, 0x00f7}, {0x874d, 0x00ce}, {0x874e, 0x008f}, +{0x874f, 0x0075}, {0x8750, 0x00bd}, {0x8751, 0x0089}, +{0x8752, 0x00f7}, {0x8753, 0x00ce}, {0x8754, 0x008f}, +{0x8755, 0x0078}, {0x8756, 0x00bd}, {0x8757, 0x0089}, +{0x8758, 0x00f7}, {0x8759, 0x00ce}, {0x875a, 0x008f}, +{0x875b, 0x007b}, {0x875c, 0x00bd}, {0x875d, 0x0089}, +{0x875e, 0x00f7}, {0x875f, 0x004f}, {0x8760, 0x00b7}, +{0x8761, 0x008f}, {0x8762, 0x007d}, {0x8763, 0x00b7}, +{0x8764, 0x008f}, {0x8765, 0x0081}, {0x8766, 0x00b6}, +{0x8767, 0x008f}, {0x8768, 0x0072}, {0x8769, 0x0027}, +{0x876a, 0x0047}, {0x876b, 0x007c}, {0x876c, 0x008f}, +{0x876d, 0x007d}, {0x876e, 0x00b6}, {0x876f, 0x008f}, +{0x8770, 0x0075}, {0x8771, 0x0027}, {0x8772, 0x003f}, +{0x8773, 0x007c}, {0x8774, 0x008f}, {0x8775, 0x007d}, +{0x8776, 0x00b6}, {0x8777, 0x008f}, {0x8778, 0x0078}, +{0x8779, 0x0027}, {0x877a, 0x0037}, {0x877b, 0x007c}, +{0x877c, 0x008f}, {0x877d, 0x007d}, {0x877e, 0x00b6}, +{0x877f, 0x008f}, {0x8780, 0x007b}, {0x8781, 0x0027}, +{0x8782, 0x002f}, {0x8783, 0x007f}, {0x8784, 0x008f}, +{0x8785, 0x007d}, {0x8786, 0x007c}, {0x8787, 0x008f}, +{0x8788, 0x0081}, {0x8789, 0x007a}, {0x878a, 0x008f}, +{0x878b, 0x0072}, {0x878c, 0x0027}, {0x878d, 0x001b}, +{0x878e, 0x007c}, {0x878f, 0x008f}, {0x8790, 0x007d}, +{0x8791, 0x007a}, {0x8792, 0x008f}, {0x8793, 0x0075}, +{0x8794, 0x0027}, {0x8795, 0x0016}, {0x8796, 0x007c}, +{0x8797, 0x008f}, {0x8798, 0x007d}, {0x8799, 0x007a}, +{0x879a, 0x008f}, {0x879b, 0x0078}, {0x879c, 0x0027}, +{0x879d, 0x0011}, {0x879e, 0x007c}, {0x879f, 0x008f}, +{0x87a0, 0x007d}, {0x87a1, 0x007a}, {0x87a2, 0x008f}, +{0x87a3, 0x007b}, {0x87a4, 0x0027}, {0x87a5, 0x000c}, +{0x87a6, 0x007e}, {0x87a7, 0x0087}, {0x87a8, 0x0083}, +{0x87a9, 0x007a}, {0x87aa, 0x008f}, {0x87ab, 0x0075}, +{0x87ac, 0x007a}, {0x87ad, 0x008f}, {0x87ae, 0x0078}, +{0x87af, 0x007a}, {0x87b0, 0x008f}, {0x87b1, 0x007b}, +{0x87b2, 0x00ce}, {0x87b3, 0x00c1}, {0x87b4, 0x00fc}, +{0x87b5, 0x00f6}, {0x87b6, 0x008f}, {0x87b7, 0x007d}, +{0x87b8, 0x003a}, {0x87b9, 0x00a6}, {0x87ba, 0x0000}, +{0x87bb, 0x00b7}, {0x87bc, 0x0012}, {0x87bd, 0x0070}, +{0x87be, 0x00b6}, {0x87bf, 0x008f}, {0x87c0, 0x0072}, +{0x87c1, 0x0026}, {0x87c2, 0x0003}, {0x87c3, 0x007e}, +{0x87c4, 0x0087}, {0x87c5, 0x00fa}, {0x87c6, 0x00b6}, +{0x87c7, 0x008f}, {0x87c8, 0x0075}, {0x87c9, 0x0026}, +{0x87ca, 0x000a}, {0x87cb, 0x0018}, {0x87cc, 0x00ce}, +{0x87cd, 0x008f}, {0x87ce, 0x0073}, {0x87cf, 0x00bd}, +{0x87d0, 0x0089}, {0x87d1, 0x00d5}, {0x87d2, 0x007e}, +{0x87d3, 0x0087}, {0x87d4, 0x00fa}, {0x87d5, 0x00b6}, +{0x87d6, 0x008f}, {0x87d7, 0x0078}, {0x87d8, 0x0026}, +{0x87d9, 0x000a}, {0x87da, 0x0018}, {0x87db, 0x00ce}, +{0x87dc, 0x008f}, {0x87dd, 0x0076}, {0x87de, 0x00bd}, +{0x87df, 0x0089}, {0x87e0, 0x00d5}, {0x87e1, 0x007e}, +{0x87e2, 0x0087}, {0x87e3, 0x00fa}, {0x87e4, 0x00b6}, +{0x87e5, 0x008f}, {0x87e6, 0x007b}, {0x87e7, 0x0026}, +{0x87e8, 0x000a}, {0x87e9, 0x0018}, {0x87ea, 0x00ce}, +{0x87eb, 0x008f}, {0x87ec, 0x0079}, {0x87ed, 0x00bd}, +{0x87ee, 0x0089}, {0x87ef, 0x00d5}, {0x87f0, 0x007e}, +{0x87f1, 0x0087}, {0x87f2, 0x00fa}, {0x87f3, 0x0086}, +{0x87f4, 0x0005}, {0x87f5, 0x0097}, {0x87f6, 0x0040}, +{0x87f7, 0x007e}, {0x87f8, 0x0089}, {0x87f9, 0x006e}, +{0x87fa, 0x00b6}, {0x87fb, 0x008f}, {0x87fc, 0x0075}, +{0x87fd, 0x0081}, {0x87fe, 0x0007}, {0x87ff, 0x002e}, +{0x8800, 0x00f2}, {0x8801, 0x00f6}, {0x8802, 0x0012}, +{0x8803, 0x0006}, {0x8804, 0x00c4}, {0x8805, 0x00f8}, +{0x8806, 0x001b}, {0x8807, 0x00b7}, {0x8808, 0x0012}, +{0x8809, 0x0006}, {0x880a, 0x00b6}, {0x880b, 0x008f}, +{0x880c, 0x0078}, {0x880d, 0x0081}, {0x880e, 0x0007}, +{0x880f, 0x002e}, {0x8810, 0x00e2}, {0x8811, 0x0048}, +{0x8812, 0x0048}, {0x8813, 0x0048}, {0x8814, 0x00f6}, +{0x8815, 0x0012}, {0x8816, 0x0006}, {0x8817, 0x00c4}, +{0x8818, 0x00c7}, {0x8819, 0x001b}, {0x881a, 0x00b7}, +{0x881b, 0x0012}, {0x881c, 0x0006}, {0x881d, 0x00b6}, +{0x881e, 0x008f}, {0x881f, 0x007b}, {0x8820, 0x0081}, +{0x8821, 0x0007}, {0x8822, 0x002e}, {0x8823, 0x00cf}, +{0x8824, 0x00f6}, {0x8825, 0x0012}, {0x8826, 0x0005}, +{0x8827, 0x00c4}, {0x8828, 0x00f8}, {0x8829, 0x001b}, +{0x882a, 0x00b7}, {0x882b, 0x0012}, {0x882c, 0x0005}, +{0x882d, 0x0086}, {0x882e, 0x0000}, {0x882f, 0x00f6}, +{0x8830, 0x008f}, {0x8831, 0x0071}, {0x8832, 0x00bd}, +{0x8833, 0x0089}, {0x8834, 0x0094}, {0x8835, 0x0086}, +{0x8836, 0x0001}, {0x8837, 0x00f6}, {0x8838, 0x008f}, +{0x8839, 0x0074}, {0x883a, 0x00bd}, {0x883b, 0x0089}, +{0x883c, 0x0094}, {0x883d, 0x0086}, {0x883e, 0x0002}, +{0x883f, 0x00f6}, {0x8840, 0x008f}, {0x8841, 0x0077}, +{0x8842, 0x00bd}, {0x8843, 0x0089}, {0x8844, 0x0094}, +{0x8845, 0x0086}, {0x8846, 0x0003}, {0x8847, 0x00f6}, +{0x8848, 0x008f}, {0x8849, 0x007a}, {0x884a, 0x00bd}, +{0x884b, 0x0089}, {0x884c, 0x0094}, {0x884d, 0x00ce}, +{0x884e, 0x008f}, {0x884f, 0x0070}, {0x8850, 0x00a6}, +{0x8851, 0x0001}, {0x8852, 0x0081}, {0x8853, 0x0001}, +{0x8854, 0x0027}, {0x8855, 0x0007}, {0x8856, 0x0081}, +{0x8857, 0x0003}, {0x8858, 0x0027}, {0x8859, 0x0003}, +{0x885a, 0x007e}, {0x885b, 0x0088}, {0x885c, 0x0066}, +{0x885d, 0x00a6}, {0x885e, 0x0000}, {0x885f, 0x00b8}, +{0x8860, 0x008f}, {0x8861, 0x0081}, {0x8862, 0x0084}, +{0x8863, 0x0001}, {0x8864, 0x0026}, {0x8865, 0x000b}, +{0x8866, 0x008c}, {0x8867, 0x008f}, {0x8868, 0x0079}, +{0x8869, 0x002c}, {0x886a, 0x000e}, {0x886b, 0x0008}, +{0x886c, 0x0008}, {0x886d, 0x0008}, {0x886e, 0x007e}, +{0x886f, 0x0088}, {0x8870, 0x0050}, {0x8871, 0x00b6}, +{0x8872, 0x0012}, {0x8873, 0x0004}, {0x8874, 0x008a}, +{0x8875, 0x0040}, {0x8876, 0x00b7}, {0x8877, 0x0012}, +{0x8878, 0x0004}, {0x8879, 0x00b6}, {0x887a, 0x0012}, +{0x887b, 0x0004}, {0x887c, 0x0084}, {0x887d, 0x00fb}, +{0x887e, 0x0084}, {0x887f, 0x00ef}, {0x8880, 0x00b7}, +{0x8881, 0x0012}, {0x8882, 0x0004}, {0x8883, 0x00b6}, +{0x8884, 0x0012}, {0x8885, 0x0007}, {0x8886, 0x0036}, +{0x8887, 0x00b6}, {0x8888, 0x008f}, {0x8889, 0x007c}, +{0x888a, 0x0048}, {0x888b, 0x0048}, {0x888c, 0x00b7}, +{0x888d, 0x0012}, {0x888e, 0x0007}, {0x888f, 0x0086}, +{0x8890, 0x0001}, {0x8891, 0x00ba}, {0x8892, 0x0012}, +{0x8893, 0x0004}, {0x8894, 0x00b7}, {0x8895, 0x0012}, +{0x8896, 0x0004}, {0x8897, 0x0001}, {0x8898, 0x0001}, +{0x8899, 0x0001}, {0x889a, 0x0001}, {0x889b, 0x0001}, +{0x889c, 0x0001}, {0x889d, 0x0086}, {0x889e, 0x00fe}, +{0x889f, 0x00b4}, {0x88a0, 0x0012}, {0x88a1, 0x0004}, +{0x88a2, 0x00b7}, {0x88a3, 0x0012}, {0x88a4, 0x0004}, +{0x88a5, 0x0086}, {0x88a6, 0x0002}, {0x88a7, 0x00ba}, +{0x88a8, 0x0012}, {0x88a9, 0x0004}, {0x88aa, 0x00b7}, +{0x88ab, 0x0012}, {0x88ac, 0x0004}, {0x88ad, 0x0086}, +{0x88ae, 0x00fd}, {0x88af, 0x00b4}, {0x88b0, 0x0012}, +{0x88b1, 0x0004}, {0x88b2, 0x00b7}, {0x88b3, 0x0012}, +{0x88b4, 0x0004}, {0x88b5, 0x0032}, {0x88b6, 0x00b7}, +{0x88b7, 0x0012}, {0x88b8, 0x0007}, {0x88b9, 0x00b6}, +{0x88ba, 0x0012}, {0x88bb, 0x0000}, {0x88bc, 0x0084}, +{0x88bd, 0x0008}, {0x88be, 0x0081}, {0x88bf, 0x0008}, +{0x88c0, 0x0027}, {0x88c1, 0x000f}, {0x88c2, 0x007c}, +{0x88c3, 0x0082}, {0x88c4, 0x0008}, {0x88c5, 0x0026}, +{0x88c6, 0x0007}, {0x88c7, 0x0086}, {0x88c8, 0x0076}, +{0x88c9, 0x0097}, {0x88ca, 0x0040}, {0x88cb, 0x007e}, +{0x88cc, 0x0089}, {0x88cd, 0x006e}, {0x88ce, 0x007e}, +{0x88cf, 0x0086}, {0x88d0, 0x00ec}, {0x88d1, 0x00b6}, +{0x88d2, 0x008f}, {0x88d3, 0x007f}, {0x88d4, 0x0081}, +{0x88d5, 0x000f}, {0x88d6, 0x0027}, {0x88d7, 0x003c}, +{0x88d8, 0x00bd}, {0x88d9, 0x00e6}, {0x88da, 0x00c7}, +{0x88db, 0x00b7}, {0x88dc, 0x0012}, {0x88dd, 0x000d}, +{0x88de, 0x00bd}, {0x88df, 0x00e6}, {0x88e0, 0x00cb}, +{0x88e1, 0x00b6}, {0x88e2, 0x0012}, {0x88e3, 0x0004}, +{0x88e4, 0x008a}, {0x88e5, 0x0020}, {0x88e6, 0x00b7}, +{0x88e7, 0x0012}, {0x88e8, 0x0004}, {0x88e9, 0x00ce}, +{0x88ea, 0x00ff}, {0x88eb, 0x00ff}, {0x88ec, 0x00b6}, +{0x88ed, 0x0012}, {0x88ee, 0x0000}, {0x88ef, 0x0081}, +{0x88f0, 0x000c}, {0x88f1, 0x0026}, {0x88f2, 0x0005}, +{0x88f3, 0x0009}, {0x88f4, 0x0026}, {0x88f5, 0x00f6}, +{0x88f6, 0x0027}, {0x88f7, 0x001c}, {0x88f8, 0x00b6}, +{0x88f9, 0x0012}, {0x88fa, 0x0004}, {0x88fb, 0x0084}, +{0x88fc, 0x00df}, {0x88fd, 0x00b7}, {0x88fe, 0x0012}, +{0x88ff, 0x0004}, {0x8900, 0x0096}, {0x8901, 0x0083}, +{0x8902, 0x0081}, {0x8903, 0x0007}, {0x8904, 0x002c}, +{0x8905, 0x0005}, {0x8906, 0x007c}, {0x8907, 0x0000}, +{0x8908, 0x0083}, {0x8909, 0x0020}, {0x890a, 0x0006}, +{0x890b, 0x0096}, {0x890c, 0x0083}, {0x890d, 0x008b}, +{0x890e, 0x0008}, {0x890f, 0x0097}, {0x8910, 0x0083}, +{0x8911, 0x007e}, {0x8912, 0x0085}, {0x8913, 0x0041}, +{0x8914, 0x007f}, {0x8915, 0x008f}, {0x8916, 0x007e}, +{0x8917, 0x0086}, {0x8918, 0x0080}, {0x8919, 0x00b7}, +{0x891a, 0x0012}, {0x891b, 0x000c}, {0x891c, 0x0086}, +{0x891d, 0x0001}, {0x891e, 0x00b7}, {0x891f, 0x008f}, +{0x8920, 0x007d}, {0x8921, 0x00b6}, {0x8922, 0x0012}, +{0x8923, 0x000c}, {0x8924, 0x0084}, {0x8925, 0x007f}, +{0x8926, 0x00b7}, {0x8927, 0x0012}, {0x8928, 0x000c}, +{0x8929, 0x008a}, {0x892a, 0x0080}, {0x892b, 0x00b7}, +{0x892c, 0x0012}, {0x892d, 0x000c}, {0x892e, 0x0086}, +{0x892f, 0x000a}, {0x8930, 0x00bd}, {0x8931, 0x008a}, +{0x8932, 0x0006}, {0x8933, 0x00b6}, {0x8934, 0x0012}, +{0x8935, 0x000a}, {0x8936, 0x002a}, {0x8937, 0x0009}, +{0x8938, 0x00b6}, {0x8939, 0x0012}, {0x893a, 0x000c}, +{0x893b, 0x00ba}, {0x893c, 0x008f}, {0x893d, 0x007d}, +{0x893e, 0x00b7}, {0x893f, 0x0012}, {0x8940, 0x000c}, +{0x8941, 0x00b6}, {0x8942, 0x008f}, {0x8943, 0x007e}, +{0x8944, 0x0081}, {0x8945, 0x0060}, {0x8946, 0x0027}, +{0x8947, 0x001a}, {0x8948, 0x008b}, {0x8949, 0x0020}, +{0x894a, 0x00b7}, {0x894b, 0x008f}, {0x894c, 0x007e}, +{0x894d, 0x00b6}, {0x894e, 0x0012}, {0x894f, 0x000c}, +{0x8950, 0x0084}, {0x8951, 0x009f}, {0x8952, 0x00ba}, +{0x8953, 0x008f}, {0x8954, 0x007e}, {0x8955, 0x00b7}, +{0x8956, 0x0012}, {0x8957, 0x000c}, {0x8958, 0x00b6}, +{0x8959, 0x008f}, {0x895a, 0x007d}, {0x895b, 0x0048}, +{0x895c, 0x00b7}, {0x895d, 0x008f}, {0x895e, 0x007d}, +{0x895f, 0x007e}, {0x8960, 0x0089}, {0x8961, 0x0021}, +{0x8962, 0x00b6}, {0x8963, 0x0012}, {0x8964, 0x0004}, +{0x8965, 0x008a}, {0x8966, 0x0020}, {0x8967, 0x00b7}, +{0x8968, 0x0012}, {0x8969, 0x0004}, {0x896a, 0x00bd}, +{0x896b, 0x008a}, {0x896c, 0x000a}, {0x896d, 0x004f}, +{0x896e, 0x0039}, {0x896f, 0x00a6}, {0x8970, 0x0000}, +{0x8971, 0x0018}, {0x8972, 0x00a7}, {0x8973, 0x0000}, +{0x8974, 0x0008}, {0x8975, 0x0018}, {0x8976, 0x0008}, +{0x8977, 0x005a}, {0x8978, 0x0026}, {0x8979, 0x00f5}, +{0x897a, 0x0039}, {0x897b, 0x0036}, {0x897c, 0x006c}, +{0x897d, 0x0000}, {0x897e, 0x0032}, {0x897f, 0x00ba}, +{0x8980, 0x008f}, {0x8981, 0x007f}, {0x8982, 0x00b7}, +{0x8983, 0x008f}, {0x8984, 0x007f}, {0x8985, 0x00b6}, +{0x8986, 0x0012}, {0x8987, 0x0009}, {0x8988, 0x0084}, +{0x8989, 0x0003}, {0x898a, 0x00a7}, {0x898b, 0x0001}, +{0x898c, 0x00b6}, {0x898d, 0x0012}, {0x898e, 0x0006}, +{0x898f, 0x0084}, {0x8990, 0x003f}, {0x8991, 0x00a7}, +{0x8992, 0x0002}, {0x8993, 0x0039}, {0x8994, 0x0036}, +{0x8995, 0x0086}, {0x8996, 0x0003}, {0x8997, 0x00b7}, +{0x8998, 0x008f}, {0x8999, 0x0080}, {0x899a, 0x0032}, +{0x899b, 0x00c1}, {0x899c, 0x0000}, {0x899d, 0x0026}, +{0x899e, 0x0006}, {0x899f, 0x00b7}, {0x89a0, 0x008f}, +{0x89a1, 0x007c}, {0x89a2, 0x007e}, {0x89a3, 0x0089}, +{0x89a4, 0x00c9}, {0x89a5, 0x00c1}, {0x89a6, 0x0001}, +{0x89a7, 0x0027}, {0x89a8, 0x0018}, {0x89a9, 0x00c1}, +{0x89aa, 0x0002}, {0x89ab, 0x0027}, {0x89ac, 0x000c}, +{0x89ad, 0x00c1}, {0x89ae, 0x0003}, {0x89af, 0x0027}, +{0x89b0, 0x0000}, {0x89b1, 0x00f6}, {0x89b2, 0x008f}, +{0x89b3, 0x0080}, {0x89b4, 0x0005}, {0x89b5, 0x0005}, +{0x89b6, 0x00f7}, {0x89b7, 0x008f}, {0x89b8, 0x0080}, +{0x89b9, 0x00f6}, {0x89ba, 0x008f}, {0x89bb, 0x0080}, +{0x89bc, 0x0005}, {0x89bd, 0x0005}, {0x89be, 0x00f7}, +{0x89bf, 0x008f}, {0x89c0, 0x0080}, {0x89c1, 0x00f6}, +{0x89c2, 0x008f}, {0x89c3, 0x0080}, {0x89c4, 0x0005}, +{0x89c5, 0x0005}, {0x89c6, 0x00f7}, {0x89c7, 0x008f}, +{0x89c8, 0x0080}, {0x89c9, 0x00f6}, {0x89ca, 0x008f}, +{0x89cb, 0x0080}, {0x89cc, 0x0053}, {0x89cd, 0x00f4}, +{0x89ce, 0x0012}, {0x89cf, 0x0007}, {0x89d0, 0x001b}, +{0x89d1, 0x00b7}, {0x89d2, 0x0012}, {0x89d3, 0x0007}, +{0x89d4, 0x0039}, {0x89d5, 0x00ce}, {0x89d6, 0x008f}, +{0x89d7, 0x0070}, {0x89d8, 0x00a6}, {0x89d9, 0x0000}, +{0x89da, 0x0018}, {0x89db, 0x00e6}, {0x89dc, 0x0000}, +{0x89dd, 0x0018}, {0x89de, 0x00a7}, {0x89df, 0x0000}, +{0x89e0, 0x00e7}, {0x89e1, 0x0000}, {0x89e2, 0x00a6}, +{0x89e3, 0x0001}, {0x89e4, 0x0018}, {0x89e5, 0x00e6}, +{0x89e6, 0x0001}, {0x89e7, 0x0018}, {0x89e8, 0x00a7}, +{0x89e9, 0x0001}, {0x89ea, 0x00e7}, {0x89eb, 0x0001}, +{0x89ec, 0x00a6}, {0x89ed, 0x0002}, {0x89ee, 0x0018}, +{0x89ef, 0x00e6}, {0x89f0, 0x0002}, {0x89f1, 0x0018}, +{0x89f2, 0x00a7}, {0x89f3, 0x0002}, {0x89f4, 0x00e7}, +{0x89f5, 0x0002}, {0x89f6, 0x0039}, {0x89f7, 0x00a6}, +{0x89f8, 0x0000}, {0x89f9, 0x0084}, {0x89fa, 0x0007}, +{0x89fb, 0x00e6}, {0x89fc, 0x0000}, {0x89fd, 0x00c4}, +{0x89fe, 0x0038}, {0x89ff, 0x0054}, {0x8a00, 0x0054}, +{0x8a01, 0x0054}, {0x8a02, 0x001b}, {0x8a03, 0x00a7}, +{0x8a04, 0x0000}, {0x8a05, 0x0039}, {0x8a06, 0x004a}, +{0x8a07, 0x0026}, {0x8a08, 0x00fd}, {0x8a09, 0x0039}, +{0x8a0a, 0x0096}, {0x8a0b, 0x0022}, {0x8a0c, 0x0084}, +{0x8a0d, 0x000f}, {0x8a0e, 0x0097}, {0x8a0f, 0x0022}, +{0x8a10, 0x0086}, {0x8a11, 0x0001}, {0x8a12, 0x00b7}, +{0x8a13, 0x008f}, {0x8a14, 0x0070}, {0x8a15, 0x00b6}, +{0x8a16, 0x0012}, {0x8a17, 0x0007}, {0x8a18, 0x00b7}, +{0x8a19, 0x008f}, {0x8a1a, 0x0071}, {0x8a1b, 0x00f6}, +{0x8a1c, 0x0012}, {0x8a1d, 0x000c}, {0x8a1e, 0x00c4}, +{0x8a1f, 0x000f}, {0x8a20, 0x00c8}, {0x8a21, 0x000f}, +{0x8a22, 0x00f7}, {0x8a23, 0x008f}, {0x8a24, 0x0072}, +{0x8a25, 0x00f6}, {0x8a26, 0x008f}, {0x8a27, 0x0072}, +{0x8a28, 0x00b6}, {0x8a29, 0x008f}, {0x8a2a, 0x0071}, +{0x8a2b, 0x0084}, {0x8a2c, 0x0003}, {0x8a2d, 0x0027}, +{0x8a2e, 0x0014}, {0x8a2f, 0x0081}, {0x8a30, 0x0001}, +{0x8a31, 0x0027}, {0x8a32, 0x001c}, {0x8a33, 0x0081}, +{0x8a34, 0x0002}, {0x8a35, 0x0027}, {0x8a36, 0x0024}, +{0x8a37, 0x00f4}, {0x8a38, 0x008f}, {0x8a39, 0x0070}, +{0x8a3a, 0x0027}, {0x8a3b, 0x002a}, {0x8a3c, 0x0096}, +{0x8a3d, 0x0022}, {0x8a3e, 0x008a}, {0x8a3f, 0x0080}, +{0x8a40, 0x007e}, {0x8a41, 0x008a}, {0x8a42, 0x0064}, +{0x8a43, 0x00f4}, {0x8a44, 0x008f}, {0x8a45, 0x0070}, +{0x8a46, 0x0027}, {0x8a47, 0x001e}, {0x8a48, 0x0096}, +{0x8a49, 0x0022}, {0x8a4a, 0x008a}, {0x8a4b, 0x0010}, +{0x8a4c, 0x007e}, {0x8a4d, 0x008a}, {0x8a4e, 0x0064}, +{0x8a4f, 0x00f4}, {0x8a50, 0x008f}, {0x8a51, 0x0070}, +{0x8a52, 0x0027}, {0x8a53, 0x0012}, {0x8a54, 0x0096}, +{0x8a55, 0x0022}, {0x8a56, 0x008a}, {0x8a57, 0x0020}, +{0x8a58, 0x007e}, {0x8a59, 0x008a}, {0x8a5a, 0x0064}, +{0x8a5b, 0x00f4}, {0x8a5c, 0x008f}, {0x8a5d, 0x0070}, +{0x8a5e, 0x0027}, {0x8a5f, 0x0006}, {0x8a60, 0x0096}, +{0x8a61, 0x0022}, {0x8a62, 0x008a}, {0x8a63, 0x0040}, +{0x8a64, 0x0097}, {0x8a65, 0x0022}, {0x8a66, 0x0074}, +{0x8a67, 0x008f}, {0x8a68, 0x0071}, {0x8a69, 0x0074}, +{0x8a6a, 0x008f}, {0x8a6b, 0x0071}, {0x8a6c, 0x0078}, +{0x8a6d, 0x008f}, {0x8a6e, 0x0070}, {0x8a6f, 0x00b6}, +{0x8a70, 0x008f}, {0x8a71, 0x0070}, {0x8a72, 0x0085}, +{0x8a73, 0x0010}, {0x8a74, 0x0027}, {0x8a75, 0x00af}, +{0x8a76, 0x00d6}, {0x8a77, 0x0022}, {0x8a78, 0x00c4}, +{0x8a79, 0x0010}, {0x8a7a, 0x0058}, {0x8a7b, 0x00b6}, +{0x8a7c, 0x0012}, {0x8a7d, 0x0070}, {0x8a7e, 0x0081}, +{0x8a7f, 0x00e4}, {0x8a80, 0x0027}, {0x8a81, 0x0036}, +{0x8a82, 0x0081}, {0x8a83, 0x00e1}, {0x8a84, 0x0026}, +{0x8a85, 0x000c}, {0x8a86, 0x0096}, {0x8a87, 0x0022}, +{0x8a88, 0x0084}, {0x8a89, 0x0020}, {0x8a8a, 0x0044}, +{0x8a8b, 0x001b}, {0x8a8c, 0x00d6}, {0x8a8d, 0x0022}, +{0x8a8e, 0x00c4}, {0x8a8f, 0x00cf}, {0x8a90, 0x0020}, +{0x8a91, 0x0023}, {0x8a92, 0x0058}, {0x8a93, 0x0081}, +{0x8a94, 0x00c6}, {0x8a95, 0x0026}, {0x8a96, 0x000d}, +{0x8a97, 0x0096}, {0x8a98, 0x0022}, {0x8a99, 0x0084}, +{0x8a9a, 0x0040}, {0x8a9b, 0x0044}, {0x8a9c, 0x0044}, +{0x8a9d, 0x001b}, {0x8a9e, 0x00d6}, {0x8a9f, 0x0022}, +{0x8aa0, 0x00c4}, {0x8aa1, 0x00af}, {0x8aa2, 0x0020}, +{0x8aa3, 0x0011}, {0x8aa4, 0x0058}, {0x8aa5, 0x0081}, +{0x8aa6, 0x0027}, {0x8aa7, 0x0026}, {0x8aa8, 0x000f}, +{0x8aa9, 0x0096}, {0x8aaa, 0x0022}, {0x8aab, 0x0084}, +{0x8aac, 0x0080}, {0x8aad, 0x0044}, {0x8aae, 0x0044}, +{0x8aaf, 0x0044}, {0x8ab0, 0x001b}, {0x8ab1, 0x00d6}, +{0x8ab2, 0x0022}, {0x8ab3, 0x00c4}, {0x8ab4, 0x006f}, +{0x8ab5, 0x001b}, {0x8ab6, 0x0097}, {0x8ab7, 0x0022}, +{0x8ab8, 0x0039}, {0x8ab9, 0x0027}, {0x8aba, 0x000c}, +{0x8abb, 0x007c}, {0x8abc, 0x0082}, {0x8abd, 0x0006}, +{0x8abe, 0x00bd}, {0x8abf, 0x00d9}, {0x8ac0, 0x00ed}, +{0x8ac1, 0x00b6}, {0x8ac2, 0x0082}, {0x8ac3, 0x0007}, +{0x8ac4, 0x007e}, {0x8ac5, 0x008a}, {0x8ac6, 0x00b9}, +{0x8ac7, 0x007f}, {0x8ac8, 0x0082}, {0x8ac9, 0x0006}, +{0x8aca, 0x0039}, { 0x0, 0x0 } +}; +#endif + + +/* phy types */ +#define CAS_PHY_UNKNOWN 0x00 +#define CAS_PHY_SERDES 0x01 +#define CAS_PHY_MII_MDIO0 0x02 +#define CAS_PHY_MII_MDIO1 0x04 +#define CAS_PHY_MII(x) ((x) & (CAS_PHY_MII_MDIO0 | CAS_PHY_MII_MDIO1)) + +/* _RING_INDEX is the index for the ring sizes to be used. _RING_SIZE + * is the actual size. the default index for the various rings is + * 8. NOTE: there a bunch of alignment constraints for the rings. to + * deal with that, i just allocate rings to create the desired + * alignment. here are the constraints: + * RX DESC and COMP rings must be 8KB aligned + * TX DESC must be 2KB aligned. + * if you change the numbers, be cognizant of how the alignment will change + * in INIT_BLOCK as well. + */ + +#define DESC_RING_I_TO_S(x) (32*(1 << (x))) +#define COMP_RING_I_TO_S(x) (128*(1 << (x))) +#define TX_DESC_RING_INDEX 4 /* 512 = 8k */ +#define RX_DESC_RING_INDEX 4 /* 512 = 8k */ +#define RX_COMP_RING_INDEX 4 /* 2048 = 64k: should be 4x rx ring size */ + +#if (TX_DESC_RING_INDEX > 8) || (TX_DESC_RING_INDEX < 0) +#error TX_DESC_RING_INDEX must be between 0 and 8 +#endif + +#if (RX_DESC_RING_INDEX > 8) || (RX_DESC_RING_INDEX < 0) +#error RX_DESC_RING_INDEX must be between 0 and 8 +#endif + +#if (RX_COMP_RING_INDEX > 8) || (RX_COMP_RING_INDEX < 0) +#error RX_COMP_RING_INDEX must be between 0 and 8 +#endif + +#define N_TX_RINGS MAX_TX_RINGS /* for QoS */ +#define N_TX_RINGS_MASK MAX_TX_RINGS_MASK +#define N_RX_DESC_RINGS MAX_RX_DESC_RINGS /* 1 for ipsec */ +#define N_RX_COMP_RINGS 0x1 /* for mult. PCI interrupts */ + +/* number of flows that can go through re-assembly */ +#define N_RX_FLOWS 64 + +#define TX_DESC_RING_SIZE DESC_RING_I_TO_S(TX_DESC_RING_INDEX) +#define RX_DESC_RING_SIZE DESC_RING_I_TO_S(RX_DESC_RING_INDEX) +#define RX_COMP_RING_SIZE COMP_RING_I_TO_S(RX_COMP_RING_INDEX) +#define TX_DESC_RINGN_INDEX(x) TX_DESC_RING_INDEX +#define RX_DESC_RINGN_INDEX(x) RX_DESC_RING_INDEX +#define RX_COMP_RINGN_INDEX(x) RX_COMP_RING_INDEX +#define TX_DESC_RINGN_SIZE(x) TX_DESC_RING_SIZE +#define RX_DESC_RINGN_SIZE(x) RX_DESC_RING_SIZE +#define RX_COMP_RINGN_SIZE(x) RX_COMP_RING_SIZE + +/* convert values */ +#define CAS_BASE(x, y) (((y) << (x ## _SHIFT)) & (x ## _MASK)) +#define CAS_VAL(x, y) (((y) & (x ## _MASK)) >> (x ## _SHIFT)) +#define CAS_TX_RINGN_BASE(y) ((TX_DESC_RINGN_INDEX(y) << \ + TX_CFG_DESC_RINGN_SHIFT(y)) & \ + TX_CFG_DESC_RINGN_MASK(y)) + +/* min is 2k, but we can't do jumbo frames unless it's at least 8k */ +#define CAS_MIN_PAGE_SHIFT 11 /* 2048 */ +#define CAS_JUMBO_PAGE_SHIFT 13 /* 8192 */ +#define CAS_MAX_PAGE_SHIFT 14 /* 16384 */ + +#define TX_DESC_BUFLEN_MASK 0x0000000000003FFFULL /* buffer length in + bytes. 0 - 9256 */ +#define TX_DESC_BUFLEN_SHIFT 0 +#define TX_DESC_CSUM_START_MASK 0x00000000001F8000ULL /* checksum start. # + of bytes to be + skipped before + csum calc begins. + value must be + even */ +#define TX_DESC_CSUM_START_SHIFT 15 +#define TX_DESC_CSUM_STUFF_MASK 0x000000001FE00000ULL /* checksum stuff. + byte offset w/in + the pkt for the + 1st csum byte. + must be > 8 */ +#define TX_DESC_CSUM_STUFF_SHIFT 21 +#define TX_DESC_CSUM_EN 0x0000000020000000ULL /* enable checksum */ +#define TX_DESC_EOF 0x0000000040000000ULL /* end of frame */ +#define TX_DESC_SOF 0x0000000080000000ULL /* start of frame */ +#define TX_DESC_INTME 0x0000000100000000ULL /* interrupt me */ +#define TX_DESC_NO_CRC 0x0000000200000000ULL /* debugging only. + CRC will not be + inserted into + outgoing frame. */ +struct cas_tx_desc { + u64 control; + u64 buffer; +}; + +/* descriptor ring for free buffers contains page-sized buffers. the index + * value is not used by the hw in any way. it's just stored and returned in + * the completion ring. + */ +struct cas_rx_desc { + u64 index; + u64 buffer; +}; + +/* received packets are put on the completion ring. */ +/* word 1 */ +#define RX_COMP1_DATA_SIZE_MASK 0x0000000007FFE000ULL +#define RX_COMP1_DATA_SIZE_SHIFT 13 +#define RX_COMP1_DATA_OFF_MASK 0x000001FFF8000000ULL +#define RX_COMP1_DATA_OFF_SHIFT 27 +#define RX_COMP1_DATA_INDEX_MASK 0x007FFE0000000000ULL +#define RX_COMP1_DATA_INDEX_SHIFT 41 +#define RX_COMP1_SKIP_MASK 0x0180000000000000ULL +#define RX_COMP1_SKIP_SHIFT 55 +#define RX_COMP1_RELEASE_NEXT 0x0200000000000000ULL +#define RX_COMP1_SPLIT_PKT 0x0400000000000000ULL +#define RX_COMP1_RELEASE_FLOW 0x0800000000000000ULL +#define RX_COMP1_RELEASE_DATA 0x1000000000000000ULL +#define RX_COMP1_RELEASE_HDR 0x2000000000000000ULL +#define RX_COMP1_TYPE_MASK 0xC000000000000000ULL +#define RX_COMP1_TYPE_SHIFT 62 + +/* word 2 */ +#define RX_COMP2_NEXT_INDEX_MASK 0x00000007FFE00000ULL +#define RX_COMP2_NEXT_INDEX_SHIFT 21 +#define RX_COMP2_HDR_SIZE_MASK 0x00000FF800000000ULL +#define RX_COMP2_HDR_SIZE_SHIFT 35 +#define RX_COMP2_HDR_OFF_MASK 0x0003F00000000000ULL +#define RX_COMP2_HDR_OFF_SHIFT 44 +#define RX_COMP2_HDR_INDEX_MASK 0xFFFC000000000000ULL +#define RX_COMP2_HDR_INDEX_SHIFT 50 + +/* word 3 */ +#define RX_COMP3_SMALL_PKT 0x0000000000000001ULL +#define RX_COMP3_JUMBO_PKT 0x0000000000000002ULL +#define RX_COMP3_JUMBO_HDR_SPLIT_EN 0x0000000000000004ULL +#define RX_COMP3_CSUM_START_MASK 0x000000000007F000ULL +#define RX_COMP3_CSUM_START_SHIFT 12 +#define RX_COMP3_FLOWID_MASK 0x0000000001F80000ULL +#define RX_COMP3_FLOWID_SHIFT 19 +#define RX_COMP3_OPCODE_MASK 0x000000000E000000ULL +#define RX_COMP3_OPCODE_SHIFT 25 +#define RX_COMP3_FORCE_FLAG 0x0000000010000000ULL +#define RX_COMP3_NO_ASSIST 0x0000000020000000ULL +#define RX_COMP3_LOAD_BAL_MASK 0x000001F800000000ULL +#define RX_COMP3_LOAD_BAL_SHIFT 35 +#define RX_PLUS_COMP3_ENC_PKT 0x0000020000000000ULL /* cas+ */ +#define RX_COMP3_L3_HEAD_OFF_MASK 0x0000FE0000000000ULL /* cas */ +#define RX_COMP3_L3_HEAD_OFF_SHIFT 41 +#define RX_PLUS_COMP_L3_HEAD_OFF_MASK 0x0000FC0000000000ULL /* cas+ */ +#define RX_PLUS_COMP_L3_HEAD_OFF_SHIFT 42 +#define RX_COMP3_SAP_MASK 0xFFFF000000000000ULL +#define RX_COMP3_SAP_SHIFT 48 + +/* word 4 */ +#define RX_COMP4_TCP_CSUM_MASK 0x000000000000FFFFULL +#define RX_COMP4_TCP_CSUM_SHIFT 0 +#define RX_COMP4_PKT_LEN_MASK 0x000000003FFF0000ULL +#define RX_COMP4_PKT_LEN_SHIFT 16 +#define RX_COMP4_PERFECT_MATCH_MASK 0x00000003C0000000ULL +#define RX_COMP4_PERFECT_MATCH_SHIFT 30 +#define RX_COMP4_ZERO 0x0000080000000000ULL +#define RX_COMP4_HASH_VAL_MASK 0x0FFFF00000000000ULL +#define RX_COMP4_HASH_VAL_SHIFT 44 +#define RX_COMP4_HASH_PASS 0x1000000000000000ULL +#define RX_COMP4_BAD 0x4000000000000000ULL +#define RX_COMP4_LEN_MISMATCH 0x8000000000000000ULL + +/* we encode the following: ring/index/release. only 14 bits + * are usable. + * NOTE: the encoding is dependent upon RX_DESC_RING_SIZE and + * MAX_RX_DESC_RINGS. */ +#define RX_INDEX_NUM_MASK 0x0000000000000FFFULL +#define RX_INDEX_NUM_SHIFT 0 +#define RX_INDEX_RING_MASK 0x0000000000001000ULL +#define RX_INDEX_RING_SHIFT 12 +#define RX_INDEX_RELEASE 0x0000000000002000ULL + +struct cas_rx_comp { + u64 word1; + u64 word2; + u64 word3; + u64 word4; +}; + +enum link_state { + link_down = 0, /* No link, will retry */ + link_aneg, /* Autoneg in progress */ + link_force_try, /* Try Forced link speed */ + link_force_ret, /* Forced mode worked, retrying autoneg */ + link_force_ok, /* Stay in forced mode */ + link_up /* Link is up */ +}; + +typedef struct cas_page { + struct list_head list; + struct page *buffer; + dma_addr_t dma_addr; + int used; +} cas_page_t; + + +/* some alignment constraints: + * TX DESC, RX DESC, and RX COMP must each be 8K aligned. + * TX COMPWB must be 8-byte aligned. + * to accomplish this, here's what we do: + * + * INIT_BLOCK_RX_COMP = 64k (already aligned) + * INIT_BLOCK_RX_DESC = 8k + * INIT_BLOCK_TX = 8k + * INIT_BLOCK_RX1_DESC = 8k + * TX COMPWB + */ +#define INIT_BLOCK_TX (TX_DESC_RING_SIZE) +#define INIT_BLOCK_RX_DESC (RX_DESC_RING_SIZE) +#define INIT_BLOCK_RX_COMP (RX_COMP_RING_SIZE) + +struct cas_init_block { + struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP]; + struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC]; + struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX]; + u64 tx_compwb; +}; + +/* tiny buffers to deal with target abort issue. we allocate a bit + * over so that we don't have target abort issues with these buffers + * as well. + */ +#define TX_TINY_BUF_LEN 0x100 +#define TX_TINY_BUF_BLOCK ((INIT_BLOCK_TX + 1)*TX_TINY_BUF_LEN) + +struct cas_tiny_count { + int nbufs; + int used; +}; + +struct cas { + spinlock_t lock; /* for most bits */ + spinlock_t tx_lock[N_TX_RINGS]; /* tx bits */ + spinlock_t stat_lock[N_TX_RINGS + 1]; /* for stat gathering */ + spinlock_t rx_inuse_lock; /* rx inuse list */ + spinlock_t rx_spare_lock; /* rx spare list */ + + void __iomem *regs; + int tx_new[N_TX_RINGS], tx_old[N_TX_RINGS]; + int rx_old[N_RX_DESC_RINGS]; + int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS]; + int rx_last[N_RX_DESC_RINGS]; + + /* Set when chip is actually in operational state + * (ie. not power managed) */ + int hw_running; + int opened; + struct semaphore pm_sem; /* open/close/suspend/resume */ + + struct cas_init_block *init_block; + struct cas_tx_desc *init_txds[MAX_TX_RINGS]; + struct cas_rx_desc *init_rxds[MAX_RX_DESC_RINGS]; + struct cas_rx_comp *init_rxcs[MAX_RX_COMP_RINGS]; + + /* we use sk_buffs for tx and pages for rx. the rx skbuffs + * are there for flow re-assembly. */ + struct sk_buff *tx_skbs[N_TX_RINGS][TX_DESC_RING_SIZE]; + struct sk_buff_head rx_flows[N_RX_FLOWS]; + cas_page_t *rx_pages[N_RX_DESC_RINGS][RX_DESC_RING_SIZE]; + struct list_head rx_spare_list, rx_inuse_list; + int rx_spares_needed; + + /* for small packets when copying would be quicker than + mapping */ + struct cas_tiny_count tx_tiny_use[N_TX_RINGS][TX_DESC_RING_SIZE]; + u8 *tx_tiny_bufs[N_TX_RINGS]; + + u32 msg_enable; + + /* N_TX_RINGS must be >= N_RX_DESC_RINGS */ + struct net_device_stats net_stats[N_TX_RINGS + 1]; + + u32 pci_cfg[64 >> 2]; + u8 pci_revision; + + int phy_type; + int phy_addr; + u32 phy_id; +#define CAS_FLAG_1000MB_CAP 0x00000001 +#define CAS_FLAG_REG_PLUS 0x00000002 +#define CAS_FLAG_TARGET_ABORT 0x00000004 +#define CAS_FLAG_SATURN 0x00000008 +#define CAS_FLAG_RXD_POST_MASK 0x000000F0 +#define CAS_FLAG_RXD_POST_SHIFT 4 +#define CAS_FLAG_RXD_POST(x) ((1 << (CAS_FLAG_RXD_POST_SHIFT + (x))) & \ + CAS_FLAG_RXD_POST_MASK) +#define CAS_FLAG_ENTROPY_DEV 0x00000100 +#define CAS_FLAG_NO_HW_CSUM 0x00000200 + u32 cas_flags; + int packet_min; /* minimum packet size */ + int tx_fifo_size; + int rx_fifo_size; + int rx_pause_off; + int rx_pause_on; + int crc_size; /* 4 if half-duplex */ + + int pci_irq_INTC; + int min_frame_size; /* for tx fifo workaround */ + + /* page size allocation */ + int page_size; + int page_order; + int mtu_stride; + + u32 mac_rx_cfg; + + /* Autoneg & PHY control */ + int link_cntl; + int link_fcntl; + enum link_state lstate; + struct timer_list link_timer; + int timer_ticks; + struct work_struct reset_task; +#if 0 + atomic_t reset_task_pending; +#else + atomic_t reset_task_pending; + atomic_t reset_task_pending_mtu; + atomic_t reset_task_pending_spare; + atomic_t reset_task_pending_all; +#endif + +#ifdef CONFIG_CASSINI_QGE_DEBUG + atomic_t interrupt_seen; /* 1 if any interrupts are getting through */ +#endif + + /* Link-down problem workaround */ +#define LINK_TRANSITION_UNKNOWN 0 +#define LINK_TRANSITION_ON_FAILURE 1 +#define LINK_TRANSITION_STILL_FAILED 2 +#define LINK_TRANSITION_LINK_UP 3 +#define LINK_TRANSITION_LINK_CONFIG 4 +#define LINK_TRANSITION_LINK_DOWN 5 +#define LINK_TRANSITION_REQUESTED_RESET 6 + int link_transition; + int link_transition_jiffies_valid; + unsigned long link_transition_jiffies; + + /* Tuning */ + u8 orig_cacheline_size; /* value when loaded */ +#define CAS_PREF_CACHELINE_SIZE 0x20 /* Minimum desired */ + + /* Diagnostic counters and state. */ + int casreg_len; /* reg-space size for dumping */ + u64 pause_entered; + u16 pause_last_time_recvd; + + dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS]; + struct pci_dev *pdev; + struct net_device *dev; +}; + +#define TX_DESC_NEXT(r, x) (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1)) +#define RX_DESC_ENTRY(r, x) ((x) & (RX_DESC_RINGN_SIZE(r) - 1)) +#define RX_COMP_ENTRY(r, x) ((x) & (RX_COMP_RINGN_SIZE(r) - 1)) + +#define TX_BUFF_COUNT(r, x, y) ((x) <= (y) ? ((y) - (x)) : \ + (TX_DESC_RINGN_SIZE(r) - (x) + (y))) + +#define TX_BUFFS_AVAIL(cp, i) ((cp)->tx_old[(i)] <= (cp)->tx_new[(i)] ? \ + (cp)->tx_old[(i)] + (TX_DESC_RINGN_SIZE(i) - 1) - (cp)->tx_new[(i)] : \ + (cp)->tx_old[(i)] - (cp)->tx_new[(i)] - 1) + +#define CAS_ALIGN(addr, align) \ + (((unsigned long) (addr) + ((align) - 1UL)) & ~((align) - 1)) + +#define RX_FIFO_SIZE 16384 +#define EXPANSION_ROM_SIZE 65536 + +#define CAS_MC_EXACT_MATCH_SIZE 15 +#define CAS_MC_HASH_SIZE 256 +#define CAS_MC_HASH_MAX (CAS_MC_EXACT_MATCH_SIZE + \ + CAS_MC_HASH_SIZE) + +#define TX_TARGET_ABORT_LEN 0x20 +#define RX_SWIVEL_OFF_VAL 0x2 +#define RX_AE_FREEN_VAL(x) (RX_DESC_RINGN_SIZE(x) >> 1) +#define RX_AE_COMP_VAL (RX_COMP_RING_SIZE >> 1) +#define RX_BLANK_INTR_PKT_VAL 0x05 +#define RX_BLANK_INTR_TIME_VAL 0x0F +#define HP_TCP_THRESH_VAL 1530 /* reduce to enable reassembly */ + +#define RX_SPARE_COUNT (RX_DESC_RING_SIZE >> 1) +#define RX_SPARE_RECOVER_VAL (RX_SPARE_COUNT >> 2) + +#endif /* _CASSINI_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 68f11ac..eb36fd2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -392,6 +392,7 @@ #define PCI_DEVICE_ID_NS_87560_USB 0x0012 #define PCI_DEVICE_ID_NS_83815 0x0020 #define PCI_DEVICE_ID_NS_83820 0x0022 +#define PCI_DEVICE_ID_NS_SATURN 0x0035 #define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500 #define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501 #define PCI_DEVICE_ID_NS_SCx200_IDE 0x0502 @@ -983,6 +984,7 @@ #define PCI_DEVICE_ID_SUN_SABRE 0xa000 #define PCI_DEVICE_ID_SUN_HUMMINGBIRD 0xa001 #define PCI_DEVICE_ID_SUN_TOMATILLO 0xa801 +#define PCI_DEVICE_ID_SUN_CASSINI 0xabba #define PCI_VENDOR_ID_CMD 0x1095 #define PCI_DEVICE_ID_CMD_640 0x0640 -- cgit v0.10.2 From c3c4ed652e8f2c348ebdd3f2e45664a0e238ee52 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 27 Sep 2005 15:42:58 -0700 Subject: [ROSE]: do proto_unregister() on exit paths Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5acb168..a190eae 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1481,12 +1481,14 @@ static int __init rose_proto_init(void) if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); + proto_unregister(&rose_proto); return -1; } dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); + proto_unregister(&rose_proto); return -1; } -- cgit v0.10.2 From 70ff3b66d79c5110e533f3f2aea1a5b2fc5f8d90 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 27 Sep 2005 15:43:46 -0700 Subject: [ROSE]: return sane -E* from rose_proto_init() Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a190eae..dbfb0e3 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1482,14 +1482,14 @@ static int __init rose_proto_init(void) if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); proto_unregister(&rose_proto); - return -1; + return -EINVAL; } dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); proto_unregister(&rose_proto); - return -1; + return -ENOMEM; } memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*)); @@ -1502,9 +1502,11 @@ static int __init rose_proto_init(void) name, rose_setup); if (!dev) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); + rc = -ENOMEM; goto fail; } - if (register_netdev(dev)) { + rc = register_netdev(dev); + if (rc) { printk(KERN_ERR "ROSE: netdevice regeistration failed\n"); free_netdev(dev); goto fail; @@ -1539,7 +1541,7 @@ fail: } kfree(dev_rose); proto_unregister(&rose_proto); - return -ENOMEM; + goto out; } module_init(rose_proto_init); -- cgit v0.10.2 From a83cd2cc90bd9390cf03cd40bba204d9ed520633 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 27 Sep 2005 15:44:36 -0700 Subject: [ROSE]: check rose_ndevs earlier * Don't bother with proto registering if rose_ndevs is bad. * Make escape structure more coherent. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index dbfb0e3..0f96565 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1472,24 +1472,25 @@ static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 static int __init rose_proto_init(void) { int i; - int rc = proto_register(&rose_proto, 0); + int rc; + if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { + printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); + rc = -EINVAL; + goto out; + } + + rc = proto_register(&rose_proto, 0); if (rc != 0) goto out; rose_callsign = null_ax25_address; - if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { - printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); - proto_unregister(&rose_proto); - return -EINVAL; - } - dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL); if (dev_rose == NULL) { printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n"); - proto_unregister(&rose_proto); - return -ENOMEM; + rc = -ENOMEM; + goto out_proto_unregister; } memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*)); @@ -1540,6 +1541,7 @@ fail: free_netdev(dev_rose[i]); } kfree(dev_rose); +out_proto_unregister: proto_unregister(&rose_proto); goto out; } -- cgit v0.10.2 From 520d1b830a93086c1f9e969d98f7ef01f0356493 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 27 Sep 2005 15:45:15 -0700 Subject: [ROSE]: fix typo (regeistration) Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 0f96565..829fdbc 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1508,7 +1508,7 @@ static int __init rose_proto_init(void) } rc = register_netdev(dev); if (rc) { - printk(KERN_ERR "ROSE: netdevice regeistration failed\n"); + printk(KERN_ERR "ROSE: netdevice registration failed\n"); free_netdev(dev); goto fail; } -- cgit v0.10.2 From 2fab35d78f32fc107e1af4b1ec23f557fa20d911 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 27 Sep 2005 15:59:43 -0700 Subject: [NET]: Fix GCC4 compile error: sysctl in linux/if_ether.h The following is generated when compiling a recent (2.6.14-rc2-git5) kernel configured for ARM, with GCC4. CC init/main.o In file included from include/linux/netdevice.h:29, from include/net/sock.h:48, from init/main.c:50: include/linux/if_ether.h:114: error: array type has incomplete element type It seems that if CONFIG_SYSCTL is not set, then the compiler will throw an error due to the definition of the ether_table[] array Attached is a solution to the problem Signed-off-by: Ben Dooks Signed-off-by: David S. Miller diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index fc2d4c8..d21c305 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -111,7 +111,9 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) return (struct ethhdr *)skb->mac.raw; } +#ifdef CONFIG_SYSCTL extern struct ctl_table ether_table[]; #endif +#endif #endif /* _LINUX_IF_ETHER_H */ -- cgit v0.10.2 From ba645c16026ed733a51f904df34756f61bc155fc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 16:03:05 -0700 Subject: [NET]: Slightly optimize ethernet address comparison. We know the thing is at least 2-byte aligned, so take advantage of that instead of invoking memcmp() which results in truly horrifically inefficient code because it can't assume anything about alignment. Signed-off-by: David S. Miller diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 87a052a..8b299cc 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -146,6 +146,19 @@ int eth_rebuild_header(struct sk_buff *skb) return 0; } +static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b) +{ + const unsigned short *dest = (unsigned short *) __a; + const unsigned short *devaddr = (unsigned short *) __b; + unsigned int res; + + BUILD_BUG_ON(ETH_ALEN != 6); + res = ((dest[0] ^ devaddr[0]) | + (dest[1] ^ devaddr[1]) | + (dest[2] ^ devaddr[2])) != 0; + + return res; +} /* * Determine the packet's protocol ID. The rule here is that we @@ -158,16 +171,15 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) struct ethhdr *eth; unsigned char *rawp; - skb->mac.raw=skb->data; + skb->mac.raw = skb->data; skb_pull(skb,ETH_HLEN); eth = eth_hdr(skb); - if(*eth->h_dest&1) - { - if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) - skb->pkt_type=PACKET_BROADCAST; + if (*eth->h_dest&1) { + if (!compare_eth_addr(eth->h_dest, dev->broadcast)) + skb->pkt_type = PACKET_BROADCAST; else - skb->pkt_type=PACKET_MULTICAST; + skb->pkt_type = PACKET_MULTICAST; } /* @@ -178,10 +190,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) * seems to set IFF_PROMISC. */ - else if(1 /*dev->flags&IFF_PROMISC*/) - { - if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) - skb->pkt_type=PACKET_OTHERHOST; + else if(1 /*dev->flags&IFF_PROMISC*/) { + if (unlikely(!compare_eth_addr(eth->h_dest, dev->dev_addr))) + skb->pkt_type = PACKET_OTHERHOST; } if (ntohs(eth->h_proto) >= 1536) -- cgit v0.10.2 From 64233bffbb50f12e576c61d1698a573c8033004a Mon Sep 17 00:00:00 2001 From: Oliver Dawid Date: Tue, 27 Sep 2005 16:11:29 -0700 Subject: [APPLETALK]: Fix broadcast bug. From: Oliver Dawid we found a bug in net/appletalk/ddp.c concerning broadcast packets. In kernel 2.4 it was working fine. The bug first occured 4 years ago when switching to new SNAP layer handling. This bug can be splitted up into a sending(1) and reception(2) problem: Sending(1) In kernel 2.4 broadcast packets were sent to a matching ethernet device and atalk_rcv() was called to receive it as "loopback" (so loopback packets were shortcutted and handled in DDP layer). When switching to the new SNAP structure, this shortcut was removed and the loopback packet was send to SNAP layer. The author forgot to replace the remote device pointer by the loopback device pointer before sending the packet to SNAP layer (by calling ddp_dl->request() ) therfor the packet was not sent back by underlying layers to ddp's atalk_rcv(). Reception(2) In atalk_rcv() a packet received by this loopback mechanism contains now the (rigth) loopback device pointer (in Kernel 2.4 it was the (wrong) remote ethernet device pointer) and therefor no matching socket will be found to deliver this packet to. Because a broadcast packet should be send to the first matching socket (as it is done in many other protocols (?)), we removed the network comparison in broadcast case. Below you will find a patch to correct this bug. Its diffed to kernel 2.6.14-rc1 Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 1d31b3a..7982656 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -100,8 +100,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, continue; if (to->sat_addr.s_net == ATADDR_ANYNET && - to->sat_addr.s_node == ATADDR_BCAST && - at->src_net == atif->address.s_net) + to->sat_addr.s_node == ATADDR_BCAST) goto found; if (to->sat_addr.s_net == at->src_net && @@ -1443,8 +1442,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, else atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); - /* Not ours, so we route the packet via the correct AppleTalk iface */ if (!atif) { + /* Not ours, so we route the packet via the correct + * AppleTalk iface + */ atalk_route_packet(skb, dev, ddp, &ddphv, origlen); goto out; } @@ -1592,9 +1593,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } else { struct atalk_addr at_hint; @@ -1603,11 +1601,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } + if (!rt) + return -ENETUNREACH; + + dev = rt->dev; SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); @@ -1677,6 +1676,20 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); /* loop back */ skb_orphan(skb); + if (ddp->deh_dnode == ATADDR_BCAST) { + struct atalk_addr at_lo; + + at_lo.s_node = 0; + at_lo.s_net = 0; + + rt = atrtr_find(&at_lo); + if (!rt) { + kfree_skb(skb); + return -ENETUNREACH; + } + dev = rt->dev; + skb->dev = dev; + } ddp_dl->request(ddp_dl, skb, dev->dev_addr); } else { SOCK_DEBUG(sk, "SK %p: send out.\n", sk); -- cgit v0.10.2 From f16af555cc46a724507da371fbac94b430c93315 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 22:37:08 -0700 Subject: [SPARC64]: Add defines for 32MB/256MB PTE page size on Ultra-IV+. Signed-off-by: David S. Miller diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 43cbb08..53d612a 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -98,7 +98,9 @@ #define _PAGE_NFO _AC(0x1000000000000000,UL) /* No Fault Only */ #define _PAGE_IE _AC(0x0800000000000000,UL) /* Invert Endianness */ #define _PAGE_SOFT2 _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ -#define _PAGE_RES1 _AC(0x0003000000000000,UL) /* Reserved */ +#define _PAGE_RES1 _AC(0x0002000000000000,UL) /* Reserved */ +#define _PAGE_SZ32MB _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ +#define _PAGE_SZ256MB _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ #define _PAGE_SN _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */ #define _PAGE_RES2 _AC(0x0000780000000000,UL) /* Reserved */ #define _PAGE_PADDR_SF _AC(0x000001FFFFFFE000,UL) /* (Spitfire) paddr[40:13]*/ -- cgit v0.10.2 From d2212bc7db13268bef0799d9ff4b2e511c284885 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Sep 2005 22:50:06 -0700 Subject: [SPARC64]: Add missing IDs for newer cpus. Also, the us3_cpufreq driver can work on Ultra-IV and IV+. They use the SAFARI bus register to control the clock divider just like Ultra-III and III+ do. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index 4875695..77ef5df 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -39,6 +39,8 @@ struct cpu_fp_info linux_sparc_fpu[] = { { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, + { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, + { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, }; #define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info)) @@ -53,6 +55,8 @@ struct cpu_iu_info linux_sparc_chips[] = { { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, + { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, + { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, }; #define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c index 9080e7c..0340041 100644 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ b/arch/sparc64/kernel/us3_cpufreq.c @@ -208,7 +208,10 @@ static int __init us3_freq_init(void) impl = ((ver >> 32) & 0xffff); if (manuf == CHEETAH_MANUF && - (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL)) { + (impl == CHEETAH_IMPL || + impl == CHEETAH_PLUS_IMPL || + impl == JAGUAR_IMPL || + impl == PANTHER_IMPL)) { struct cpufreq_driver *driver; ret = -ENOMEM; diff --git a/include/asm-sparc64/head.h b/include/asm-sparc64/head.h index b63a33c..0abd3a6 100644 --- a/include/asm-sparc64/head.h +++ b/include/asm-sparc64/head.h @@ -12,9 +12,12 @@ #define __JALAPENO_ID 0x003e0016 #define CHEETAH_MANUF 0x003e -#define CHEETAH_IMPL 0x0014 -#define CHEETAH_PLUS_IMPL 0x0015 -#define JALAPENO_IMPL 0x0016 +#define CHEETAH_IMPL 0x0014 /* Ultra-III */ +#define CHEETAH_PLUS_IMPL 0x0015 /* Ultra-III+ */ +#define JALAPENO_IMPL 0x0016 /* Ultra-IIIi */ +#define JAGUAR_IMPL 0x0018 /* Ultra-IV */ +#define PANTHER_IMPL 0x0019 /* Ultra-IV+ */ +#define SERRANO_IMPL 0x0022 /* Ultra-IIIi+ */ #define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label) \ rdpr %ver, %tmp1; \ -- cgit v0.10.2 From 8b1f3124618b54cf125dea3a074b9cf469117723 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 27 Sep 2005 21:45:18 -0700 Subject: [PATCH] mm: move_pte to remap ZERO_PAGE Move the ZERO_PAGE remapping complexity to the move_pte macro in asm-generic, have it conditionally depend on __HAVE_ARCH_MULTIPLE_ZERO_PAGE, which gets defined for MIPS. For architectures without __HAVE_ARCH_MULTIPLE_ZERO_PAGE, move_pte becomes a noop. From: Hugh Dickins Fix nasty little bug we've missed in Nick's mremap move ZERO_PAGE patch. The "pte" at that point may be a swap entry or a pte_file entry: we must check pte_present before perhaps corrupting such an entry. Patch below against 2.6.14-rc2-mm1, but the same bug is in 2.6.14-rc2's mm/mremap.c, and more dangerous there since it's affecting all arches: I think the safest course is to send Nick's patch and Yoichi's build fix and this fix (build tested) on to Linus - so only MIPS can be affected. Signed-off-by: Nick Piggin Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index f86c1e5..ff28c8b 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -158,6 +158,19 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres #define lazy_mmu_prot_update(pte) do { } while (0) #endif +#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE +#define move_pte(pte, prot, old_addr, new_addr) (pte) +#else +#define move_pte(pte, prot, old_addr, new_addr) \ +({ \ + pte_t newpte = (pte); \ + if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \ + pte_page(pte) == ZERO_PAGE(old_addr)) \ + newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \ + newpte; \ +}) +#endif + /* * When walking page tables, get the address of the next boundary, * or the end address of the range if that comes earlier. Although no diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index cbd1672..eaf5d9b 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -68,6 +68,8 @@ extern unsigned long zero_page_mask; #define ZERO_PAGE(vaddr) \ (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask))) +#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE + extern void paging_init(void); /* diff --git a/mm/mremap.c b/mm/mremap.c index a32fed4..f343fc7 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -141,10 +141,10 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr, if (dst) { pte_t pte; pte = ptep_clear_flush(vma, old_addr, src); + /* ZERO_PAGE can be dependant on virtual addr */ - if (pfn_valid(pte_pfn(pte)) && - pte_page(pte) == ZERO_PAGE(old_addr)) - pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot)); + pte = move_pte(pte, new_vma->vm_page_prot, + old_addr, new_addr); set_pte_at(mm, new_addr, dst, pte); } else error = -ENOMEM; -- cgit v0.10.2 From 909021ea7a8f4ef13af54935b87b03a20906e08a Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 27 Sep 2005 21:45:20 -0700 Subject: [PATCH] fuse: add required version info Add information about required version of the userspace library/utilities to Documentation/Changes. Also add pointer to this and to FUSE documentation from Kconfig. Thanks to Anton Altaparmakov for the reminder. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/Changes b/Documentation/Changes index 5eaab04..27232be 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -237,6 +237,12 @@ udev udev is a userspace application for populating /dev dynamically with only entries for devices actually present. udev replaces devfs. +FUSE +---- + +Needs libfuse 2.4.0 or later. Absolute minimum is 2.3.0 but mount +options 'direct_io' and 'kernel_cache' won't work. + Networking ========== @@ -390,6 +396,10 @@ udev ---- o +FUSE +---- +o + Networking ********** diff --git a/fs/Kconfig b/fs/Kconfig index 068ccea..48f5422 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -472,6 +472,9 @@ config FUSE_FS utilities is available from the FUSE homepage: + See for more information. + See for needed library/utility version. + If you want to develop a userspace FS, or if you want to use a filesystem based on FUSE, answer Y or M. -- cgit v0.10.2 From ee4e52719ce474af339f4b81ece2ce9ecf920dfd Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 27 Sep 2005 21:45:21 -0700 Subject: [PATCH] fuse: check reserved node ID values This patch checks reserved node ID values returned by lookup and creation operations. In case one of the reserved values is sent, return -EIO. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e79e49b..29f1e9f 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -96,6 +96,8 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); err = req->out.h.error; + if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID)) + err = -EIO; if (!err) { inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); @@ -152,6 +154,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, fuse_put_request(fc, req); return err; } + if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) { + fuse_put_request(fc, req); + return -EIO; + } inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { -- cgit v0.10.2 From 9ed6c2fb34a1fb493caec8a9644d05bb880a6923 Mon Sep 17 00:00:00 2001 From: Chris Sykes Date: Tue, 27 Sep 2005 21:45:22 -0700 Subject: [PATCH] Fix ext2_new_inode() failure paths Fix failure paths in ext2_new_inode() and clean up duplicated code: - DQUOT_DROP() was not being called if ext2_init_security() failed. Signed-off-by: Chris Sykes Cc: Stephen Smalley Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index c8d0703..e2d6208 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -605,27 +605,28 @@ got: insert_inode_hash(inode); if (DQUOT_ALLOC_INODE(inode)) { - DQUOT_DROP(inode); err = -ENOSPC; - goto fail2; + goto fail_drop; } + err = ext2_init_acl(inode, dir); - if (err) { - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - goto fail2; - } + if (err) + goto fail_free_drop; + err = ext2_init_security(inode,dir); - if (err) { - DQUOT_FREE_INODE(inode); - goto fail2; - } + if (err) + goto fail_free_drop; + mark_inode_dirty(inode); ext2_debug("allocating inode %lu\n", inode->i_ino); ext2_preread_inode(inode); return inode; -fail2: +fail_free_drop: + DQUOT_FREE_INODE(inode); + +fail_drop: + DQUOT_DROP(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; iput(inode); -- cgit v0.10.2 From dc7b5fd6b0d3beb41f9e5e3a94dd1eadf52209f3 Mon Sep 17 00:00:00 2001 From: Chris Sykes Date: Tue, 27 Sep 2005 21:45:23 -0700 Subject: [PATCH] Fix ext3_new_inode() failure paths Fix failure paths in ext3_new_inode() and clean up duplicated code: - DQUOT_DROP() was not being called if ext3_init_security() failed. Signed-off-by: Chris Sykes Cc: Stephen Smalley Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 9655276..6549945 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -597,27 +597,22 @@ got: ret = inode; if(DQUOT_ALLOC_INODE(inode)) { - DQUOT_DROP(inode); err = -EDQUOT; - goto fail2; + goto fail_drop; } + err = ext3_init_acl(handle, inode, dir); - if (err) { - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - goto fail2; - } + if (err) + goto fail_free_drop; + err = ext3_init_security(handle,inode, dir); - if (err) { - DQUOT_FREE_INODE(inode); - goto fail2; - } + if (err) + goto fail_free_drop; + err = ext3_mark_inode_dirty(handle, inode); if (err) { ext3_std_error(sb, err); - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - goto fail2; + goto fail_free_drop; } ext3_debug("allocating inode %lu\n", inode->i_ino); @@ -631,7 +626,11 @@ really_out: brelse(bitmap_bh); return ret; -fail2: +fail_free_drop: + DQUOT_FREE_INODE(inode); + +fail_drop: + DQUOT_DROP(inode); inode->i_flags |= S_NOQUOTA; inode->i_nlink = 0; iput(inode); -- cgit v0.10.2 From 0b8dd17762194ec77066d339e0b2866b0c66b715 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Tue, 27 Sep 2005 21:45:24 -0700 Subject: [PATCH] v9fs: fix races in fid allocation Fid management cleanup. The patch attempts to fix the races in dentry's fid management. Dentries don't keep the opened fids anymore, they are moved to the file structs. Ideally there should be no more than one fid with fidcreate equal to zero in the dentry's list of fids. v9fs_fid_create initializes the important fields (fid, fidcreated) before v9fs_fid is added to the list. v9fs_fid_lookup returns only fids that are not created by v9fs_create. v9fs_fid_get_created returns the fid created by the same process by v9fs_create (if any) and removes it from dentry's list Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 821c9c4..d95f862 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -71,21 +71,28 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) * */ -struct v9fs_fid *v9fs_fid_create(struct dentry *dentry) +struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, + struct v9fs_session_info *v9ses, int fid, int create) { struct v9fs_fid *new; + dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", + dentry, fid, create); + new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); if (new == NULL) { dprintk(DEBUG_ERROR, "Out of Memory\n"); return ERR_PTR(-ENOMEM); } - new->fid = -1; + new->fid = fid; + new->v9ses = v9ses; new->fidopen = 0; - new->fidcreate = 0; + new->fidcreate = create; new->fidclunked = 0; new->iounit = 0; + new->rdir_pos = 0; + new->rdir_fcall = NULL; if (v9fs_fid_insert(new, dentry) == 0) return new; @@ -109,6 +116,59 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) } /** + * v9fs_fid_walk_up - walks from the process current directory + * up to the specified dentry. + */ +static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) +{ + int fidnum, cfidnum, err; + struct v9fs_fid *cfid; + struct dentry *cde; + struct v9fs_session_info *v9ses; + + v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); + cfid = v9fs_fid_lookup(current->fs->pwd); + if (cfid == NULL) { + dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); + return ERR_PTR(-ENOENT); + } + + cfidnum = cfid->fid; + cde = current->fs->pwd; + /* TODO: take advantage of multiwalk */ + + fidnum = v9fs_get_idpool(&v9ses->fidpool); + if (fidnum < 0) { + dprintk(DEBUG_ERROR, "could not get a new fid num\n"); + err = -ENOENT; + goto clunk_fid; + } + + while (cde != dentry) { + if (cde == cde->d_parent) { + dprintk(DEBUG_ERROR, "can't find dentry\n"); + err = -ENOENT; + goto clunk_fid; + } + + err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); + if (err < 0) { + dprintk(DEBUG_ERROR, "problem walking to parent\n"); + goto clunk_fid; + } + + cfidnum = fidnum; + cde = cde->d_parent; + } + + return v9fs_fid_create(dentry, v9ses, fidnum, 0); + +clunk_fid: + v9fs_t_clunk(v9ses, fidnum, NULL); + return ERR_PTR(err); +} + +/** * v9fs_fid_lookup - retrieve the right fid from a particular dentry * @dentry: dentry to look for fid in * @type: intent of lookup (operation or traversal) @@ -119,49 +179,25 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) * */ -struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) +struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) { struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; struct v9fs_fid *current_fid = NULL; struct v9fs_fid *temp = NULL; struct v9fs_fid *return_fid = NULL; - int found_parent = 0; - int found_user = 0; - dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry, - type); + dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); - if (fid_list && !list_empty(fid_list)) { + if (fid_list) { list_for_each_entry_safe(current_fid, temp, fid_list, list) { - if (current_fid->uid == current->uid) { - if (return_fid == NULL) { - if ((type == FID_OP) - || (!current_fid->fidopen)) { - return_fid = current_fid; - found_user = 1; - } - } - } - if (current_fid->pid == current->real_parent->pid) { - if ((return_fid == NULL) || (found_parent) - || (found_user)) { - if ((type == FID_OP) - || (!current_fid->fidopen)) { - return_fid = current_fid; - found_parent = 1; - found_user = 0; - } - } - } - if (current_fid->pid == current->pid) { - if ((type == FID_OP) || - (!current_fid->fidopen)) { - return_fid = current_fid; - found_parent = 0; - found_user = 0; - } + if (!current_fid->fidcreate) { + return_fid = current_fid; + break; } } + + if (!return_fid) + return_fid = current_fid; } /* we are at the root but didn't match */ @@ -187,55 +223,33 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) /* XXX - there may be some duplication we can get rid of */ if (par == dentry) { - /* we need to fid_lookup the starting point */ - int fidnum = -1; - int oldfid = -1; - int result = -1; - struct v9fs_session_info *v9ses = - v9fs_inode2v9ses(current->fs->pwd->d_inode); - - current_fid = - v9fs_fid_lookup(current->fs->pwd, FID_WALK); - if (current_fid == NULL) { - dprintk(DEBUG_ERROR, - "process cwd doesn't have a fid\n"); - return return_fid; - } - oldfid = current_fid->fid; - par = current->fs->pwd; - /* TODO: take advantage of multiwalk */ + return_fid = v9fs_fid_walk_up(dentry); + if (IS_ERR(return_fid)) + return_fid = NULL; + } + } - fidnum = v9fs_get_idpool(&v9ses->fidpool); - if (fidnum < 0) { - dprintk(DEBUG_ERROR, - "could not get a new fid num\n"); - return return_fid; - } + return return_fid; +} - while (par != dentry) { - result = - v9fs_t_walk(v9ses, oldfid, fidnum, "..", - NULL); - if (result < 0) { - dprintk(DEBUG_ERROR, - "problem walking to parent\n"); - - break; - } - oldfid = fidnum; - if (par == par->d_parent) { - dprintk(DEBUG_ERROR, - "can't find dentry\n"); - break; - } - par = par->d_parent; - } - if (par == dentry) { - return_fid = v9fs_fid_create(dentry); - return_fid->fid = fidnum; +struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) +{ + struct list_head *fid_list; + struct v9fs_fid *fid, *ftmp, *ret; + + dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); + fid_list = (struct list_head *)dentry->d_fsdata; + ret = NULL; + if (fid_list) { + list_for_each_entry_safe(fid, ftmp, fid_list, list) { + if (fid->fidcreate && fid->pid == current->pid) { + list_del(&fid->list); + ret = fid; + break; } } } - return return_fid; + dprintk(DEBUG_9P, "return %p\n", ret); + return ret; } diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 7db478c..84c673a 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h @@ -25,6 +25,7 @@ #define FID_OP 0 #define FID_WALK 1 +#define FID_CREATE 2 struct v9fs_fid { struct list_head list; /* list of fids associated with a dentry */ @@ -52,6 +53,8 @@ struct v9fs_fid { struct v9fs_session_info *v9ses; /* session info for this FID */ }; -struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); +struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); +struct v9fs_fid *v9fs_fid_get_created(struct dentry *); void v9fs_fid_destroy(struct v9fs_fid *fid); -struct v9fs_fid *v9fs_fid_create(struct dentry *); +struct v9fs_fid *v9fs_fid_create(struct dentry *, + struct v9fs_session_info *v9ses, int fid, int create); diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 306c967..a6aa947 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -67,7 +67,7 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) struct dentry *dc = current->fs->pwd; dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); - if (v9fs_fid_lookup(dentry, FID_OP)) { + if (v9fs_fid_lookup(dentry)) { dprintk(DEBUG_VFS, "VALID\n"); return 1; } diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index c478a73..57a43b8 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -197,21 +197,18 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) filemap_fdatawait(inode->i_mapping); if (fidnum >= 0) { - fid->fidopen--; dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, fid->fid); - if (fid->fidopen == 0) { - if (v9fs_t_clunk(v9ses, fidnum, NULL)) - dprintk(DEBUG_ERROR, "clunk failed\n"); + if (v9fs_t_clunk(v9ses, fidnum, NULL)) + dprintk(DEBUG_ERROR, "clunk failed\n"); - v9fs_put_idpool(fid->fid, &v9ses->fidpool); - } + v9fs_put_idpool(fid->fid, &v9ses->fidpool); kfree(fid->rdir_fcall); + kfree(fid); filp->private_data = NULL; - v9fs_fid_destroy(fid); } d_drop(filp->f_dentry); diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 1f8ae7d..a4799e9 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -53,30 +53,36 @@ int v9fs_file_open(struct inode *inode, struct file *file) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK); - struct v9fs_fid *v9newfid = NULL; + struct v9fs_fid *v9fid, *fid; struct v9fs_fcall *fcall = NULL; int open_mode = 0; unsigned int iounit = 0; int newfid = -1; long result = -1; - dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file, - v9fid); + dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); + + v9fid = v9fs_fid_get_created(file->f_dentry); + if (!v9fid) + v9fid = v9fs_fid_lookup(file->f_dentry); if (!v9fid) { - struct dentry *dentry = file->f_dentry; dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); + return -EBADF; + } - /* XXX - some duplication from lookup, generalize later */ - /* basically vfs_lookup is too heavy weight */ - v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP); - if (!v9fid) - return -EBADF; + if (!v9fid->fidcreate) { + fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); + if (fid == NULL) { + dprintk(DEBUG_ERROR, "Out of Memory\n"); + return -ENOMEM; + } - v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); - if (!v9fid) - return -EBADF; + fid->fidopen = 0; + fid->fidcreate = 0; + fid->fidclunked = 0; + fid->iounit = 0; + fid->v9ses = v9ses; newfid = v9fs_get_idpool(&v9ses->fidpool); if (newfid < 0) { @@ -85,58 +91,16 @@ int v9fs_file_open(struct inode *inode, struct file *file) } result = - v9fs_t_walk(v9ses, v9fid->fid, newfid, - (char *)file->f_dentry->d_name.name, NULL); + v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); + if (result < 0) { v9fs_put_idpool(newfid, &v9ses->fidpool); dprintk(DEBUG_ERROR, "rewalk didn't work\n"); return -EBADF; } - v9fid = v9fs_fid_create(dentry); - if (v9fid == NULL) { - dprintk(DEBUG_ERROR, "couldn't insert\n"); - return -ENOMEM; - } - v9fid->fid = newfid; - } - - if (v9fid->fidcreate) { - /* create case */ - newfid = v9fid->fid; - iounit = v9fid->iounit; - v9fid->fidcreate = 0; - } else { - if (!S_ISDIR(inode->i_mode)) - newfid = v9fid->fid; - else { - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { - eprintk(KERN_WARNING, "allocation failed\n"); - return -ENOSPC; - } - /* This would be a somewhat critical clone */ - result = - v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, - &fcall); - if (result < 0) { - dprintk(DEBUG_ERROR, "clone error: %s\n", - FCALL_ERROR(fcall)); - kfree(fcall); - return result; - } - - v9newfid = v9fs_fid_create(file->f_dentry); - v9newfid->fid = newfid; - v9newfid->qid = v9fid->qid; - v9newfid->iounit = v9fid->iounit; - v9newfid->fidopen = 0; - v9newfid->fidclunked = 0; - v9newfid->v9ses = v9ses; - v9fid = v9newfid; - kfree(fcall); - } - + fid->fid = newfid; + v9fid = fid; /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ /* translate open mode appropriately */ open_mode = file->f_flags & 0x3; @@ -163,9 +127,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) iounit = fcall->params.ropen.iounit; kfree(fcall); + } else { + /* create case */ + newfid = v9fid->fid; + iounit = v9fid->iounit; + v9fid->fidcreate = 0; } - file->private_data = v9fid; v9fid->rdir_pos = 0; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b16322d..2b696ae 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -307,7 +307,7 @@ v9fs_create(struct inode *dir, struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); struct super_block *sb = dir->i_sb; struct v9fs_fid *dirfid = - v9fs_fid_lookup(file_dentry->d_parent, FID_WALK); + v9fs_fid_lookup(file_dentry->d_parent); struct v9fs_fid *fid = NULL; struct inode *file_inode = NULL; struct v9fs_fcall *fcall = NULL; @@ -317,6 +317,7 @@ v9fs_create(struct inode *dir, long newfid = -1; int result = 0; unsigned int iounit = 0; + int wfidno = -1; perm = unixmode2p9mode(v9ses, perm); @@ -350,7 +351,7 @@ v9fs_create(struct inode *dir, if (result < 0) { dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); v9fs_put_idpool(newfid, &v9ses->fidpool); - newfid = 0; + newfid = -1; goto CleanUpFid; } @@ -369,20 +370,39 @@ v9fs_create(struct inode *dir, qid = fcall->params.rcreate.qid; kfree(fcall); - fid = v9fs_fid_create(file_dentry); + fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); + dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); if (!fid) { result = -ENOMEM; goto CleanUpFid; } - fid->fid = newfid; - fid->fidopen = 0; - fid->fidcreate = 1; fid->qid = qid; fid->iounit = iounit; - fid->rdir_pos = 0; - fid->rdir_fcall = NULL; - fid->v9ses = v9ses; + + /* walk to the newly created file and put the fid in the dentry */ + wfidno = v9fs_get_idpool(&v9ses->fidpool); + if (newfid < 0) { + eprintk(KERN_WARNING, "no free fids available\n"); + return -ENOSPC; + } + + result = v9fs_t_walk(v9ses, dirfidnum, wfidno, + (char *) file_dentry->d_name.name, NULL); + if (result < 0) { + dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); + v9fs_put_idpool(wfidno, &v9ses->fidpool); + wfidno = -1; + goto CleanUpFid; + } + + if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { + if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { + v9fs_put_idpool(wfidno, &v9ses->fidpool); + } + + goto CleanUpFid; + } if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || @@ -410,11 +430,11 @@ v9fs_create(struct inode *dir, d_instantiate(file_dentry, file_inode); if (perm & V9FS_DMDIR) { - if (v9fs_t_clunk(v9ses, newfid, &fcall)) + if (!v9fs_t_clunk(v9ses, newfid, &fcall)) + v9fs_put_idpool(newfid, &v9ses->fidpool); + else dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", FCALL_ERROR(fcall)); - - v9fs_put_idpool(newfid, &v9ses->fidpool); kfree(fcall); fid->fidopen = 0; fid->fidcreate = 0; @@ -426,12 +446,22 @@ v9fs_create(struct inode *dir, CleanUpFid: kfree(fcall); - if (newfid) { - if (v9fs_t_clunk(v9ses, newfid, &fcall)) + if (newfid >= 0) { + if (!v9fs_t_clunk(v9ses, newfid, &fcall)) + v9fs_put_idpool(newfid, &v9ses->fidpool); + else + dprintk(DEBUG_ERROR, "clunk failed: %s\n", + FCALL_ERROR(fcall)); + + kfree(fcall); + } + if (wfidno >= 0) { + if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) + v9fs_put_idpool(wfidno, &v9ses->fidpool); + else dprintk(DEBUG_ERROR, "clunk failed: %s\n", FCALL_ERROR(fcall)); - v9fs_put_idpool(newfid, &v9ses->fidpool); kfree(fcall); } return result; @@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) file_inode = file->d_inode; sb = file_inode->i_sb; v9ses = v9fs_inode2v9ses(file_inode); - v9fid = v9fs_fid_lookup(file, FID_OP); + v9fid = v9fs_fid_lookup(file); if (!v9fid) { dprintk(DEBUG_ERROR, @@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, sb = dir->i_sb; v9ses = v9fs_inode2v9ses(dir); - dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); + dirfid = v9fs_fid_lookup(dentry->d_parent); if (!dirfid) { dprintk(DEBUG_ERROR, "no dirfid\n"); @@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, v9fs_put_idpool(newfid, &v9ses->fidpool); if (result == -ENOENT) { d_add(dentry, NULL); - dprintk(DEBUG_ERROR, + dprintk(DEBUG_VFS, "Return negative dentry %p count %d\n", dentry, atomic_read(&dentry->d_count)); return NULL; @@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); - fid = v9fs_fid_create(dentry); + fid = v9fs_fid_create(dentry, v9ses, newfid, 0); if (fid == NULL) { dprintk(DEBUG_ERROR, "couldn't insert\n"); result = -ENOMEM; goto FreeFcall; } - fid->fid = newfid; - fid->fidopen = 0; - fid->v9ses = v9ses; fid->qid = fcall->params.rstat.stat->qid; dentry->d_op = &v9fs_dentry_operations; @@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, { struct inode *old_inode = old_dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); - struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK); + struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); struct v9fs_fid *olddirfid = - v9fs_fid_lookup(old_dentry->d_parent, FID_WALK); + v9fs_fid_lookup(old_dentry->d_parent); struct v9fs_fid *newdirfid = - v9fs_fid_lookup(new_dentry->d_parent, FID_WALK); + v9fs_fid_lookup(new_dentry->d_parent); struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); struct v9fs_fcall *fcall = NULL; int fid = -1; @@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, { struct v9fs_fcall *fcall = NULL; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); + struct v9fs_fid *fid = v9fs_fid_lookup(dentry); int err = -EPERM; dprintk(DEBUG_VFS, "dentry: %p\n", dentry); @@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); + struct v9fs_fid *fid = v9fs_fid_lookup(dentry); struct v9fs_fcall *fcall = NULL; struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); int res = -EPERM; @@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) if (retval != 0) goto FreeFcall; - newfid = v9fs_fid_lookup(dentry, FID_OP); + newfid = v9fs_fid_lookup(dentry); /* issue a twstat */ v9fs_blank_mistat(v9ses, mistat); @@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) struct v9fs_fcall *fcall = NULL; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); - struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); + struct v9fs_fid *fid = v9fs_fid_lookup(dentry); if (!fid) { dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); @@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); struct v9fs_fcall *fcall = NULL; struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); - struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP); + struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); struct v9fs_fid *newfid = NULL; char *symname = __getname(); @@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, if (retval != 0) goto FreeMem; - newfid = v9fs_fid_lookup(dentry, FID_OP); + newfid = v9fs_fid_lookup(dentry); if (!newfid) { dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); goto FreeMem; @@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) if (retval != 0) goto FreeMem; - newfid = v9fs_fid_lookup(dentry, FID_OP); + newfid = v9fs_fid_lookup(dentry); if (!newfid) { dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); retval = -EINVAL; diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 1e2b2b5..0957f4d 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -129,8 +129,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); - kfree(v9ses); - return ERR_PTR(newfid); + return newfid; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); @@ -155,23 +154,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type sb->s_root = root; - /* Setup the Root Inode */ - root_fid = v9fs_fid_create(root); - if (root_fid == NULL) { - retval = -ENOMEM; - goto put_back_sb; - } - - root_fid->fidopen = 0; - root_fid->v9ses = v9ses; - stat_result = v9fs_t_stat(v9ses, newfid, &fcall); if (stat_result < 0) { dprintk(DEBUG_ERROR, "stat error\n"); v9fs_t_clunk(v9ses, newfid, NULL); v9fs_put_idpool(newfid, &v9ses->fidpool); } else { - root_fid->fid = newfid; + /* Setup the Root Inode */ + root_fid = v9fs_fid_create(root, v9ses, newfid, 0); + if (root_fid == NULL) { + retval = -ENOMEM; + goto put_back_sb; + } + root_fid->qid = fcall->params.rstat.stat->qid; root->d_inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); -- cgit v0.10.2 From 88bdcc5d5e9a7ea280f99262f48b70aba9d949bf Mon Sep 17 00:00:00 2001 From: Jon Burgess Date: Tue, 27 Sep 2005 21:45:26 -0700 Subject: [PATCH] dvb: fix NULL pointer dereference when loading the budget-av module Ralph Metzler wrote: > AFAIR, there is a bug in tda10021.c in tda10021_readreg() which > references state->frontend.dvb->num > This is fatal if the frontend is not at the probed address and thus > not yet registered (no dvb entry set yet -> NULL pointer ...). The attached patch should get rid of the oops. Signed-off-by: Jon Burgess Cc: Johannes Stezenbach Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 87d5f4d..eaf130e 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) - printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n", - state->frontend.dvb->num, __FUNCTION__, ret); + printk("DVB: TDA10021: %s: readreg error (ret == %i)\n", + __FUNCTION__, ret); return b1[0]; } -- cgit v0.10.2 From 249a6771afcdfaca0ac178f63343aff2c4dc2853 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 27 Sep 2005 21:45:30 -0700 Subject: [PATCH] pktcdvd: MAINTAINERS record Add a MAINTAINERS entry for the pktcdvd driver. Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 7d1dd5b..1a0d0c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1906,6 +1906,13 @@ M: joern@wh.fh-wedel.de L: linux-mtd@lists.infradead.org S: Maintained +PKTCDVD DRIVER +P: Peter Osterlund +M: petero2@telia.com +L: linux-kernel@vger.kernel.org +L: packet-writing@suse.com +S: Maintained + POSIX CLOCKS and TIMERS P: George Anzinger M: george@mvista.com -- cgit v0.10.2 From 254b54771cc4c00002f796be65d2885191dca9dc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:31 -0700 Subject: [PATCH] swsusp: remove wrong code from data_free The following patch removes some wrong code from the data_free() function in swsusp. This function could only be called if there's an error while writing the suspend image to swap, so it is not triggered easily. However, if triggered, it would probably corrupt some memory. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 1cc9ff2..8aef1b4 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -402,15 +402,14 @@ static int write_page(unsigned long addr, swp_entry_t * loc) static void data_free(void) { swp_entry_t entry; - int i; + struct pbe * p; - for (i = 0; i < nr_copy_pages; i++) { - entry = (pagedir_nosave + i)->swap_address; + for_each_pbe(p, pagedir_nosave) { + entry = p->swap_address; if (entry.val) swap_free(entry); else break; - (pagedir_nosave + i)->swap_address = (swp_entry_t){0}; } } -- cgit v0.10.2 From f2d613799af915da1fd78463ba8ec5086a0d6f92 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:32 -0700 Subject: [PATCH] swsusp: prevent possible memory leak Prevent swsusp from leaking some memory in case of an error in read_pagedir(). It also prevents the BUG_ON() from triggering if there's an error while reading swap. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 8aef1b4..0dfb249 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -1437,9 +1437,9 @@ static int read_pagedir(struct pbe *pblist) } if (error) - free_page((unsigned long)pblist); - - BUG_ON(i != swsusp_info.pagedir_pages); + free_pagedir(pblist); + else + BUG_ON(i != swsusp_info.pagedir_pages); return error; } -- cgit v0.10.2 From e3306dd5f7eb2e699f36a4a313fca4b48b18d5e1 Mon Sep 17 00:00:00 2001 From: Davide Libenzi Date: Tue, 27 Sep 2005 21:45:33 -0700 Subject: [PATCH] epoll: handle timeout overflow Handle the timeout upper boundary for epoll. Signed-off-by: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 403b90a..4284cd3 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -101,6 +101,10 @@ /* Maximum number of poll wake up nests we are allowing */ #define EP_MAX_POLLWAKE_NESTS 4 +/* Maximum msec timeout value storeable in a long int */ +#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) + + struct epoll_filefd { struct file *file; int fd; @@ -1506,8 +1510,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, * and the overflow condition. The passed timeout is in milliseconds, * that why (t * HZ) / 1000. */ - jtimeout = timeout == -1 || timeout > (MAX_SCHEDULE_TIMEOUT - 1000) / HZ ? - MAX_SCHEDULE_TIMEOUT: (timeout * HZ + 999) / 1000; + jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ? + MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000; retry: write_lock_irqsave(&ep->lock, flags); -- cgit v0.10.2 From f36462f078403c1859a7e58177b28e01b3a179e4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 27 Sep 2005 21:45:34 -0700 Subject: [PATCH] Ignore trailing whitespace on kernel parameters correctly Dave Jones says: ... if the modprobe.conf has trailing whitespace, modules fail to load with the following helpful message.. snd_intel8x0: Unknown parameter `' Previous version truncated last argument. Signed-off-by: Rusty Russell Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/params.c b/kernel/params.c index fbf1732..1a8614b 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -80,8 +80,6 @@ static char *next_arg(char *args, char **param, char **val) int in_quote = 0, quoted = 0; char *next; - /* Chew any extra spaces */ - while (*args == ' ') args++; if (*args == '"') { args++; in_quote = 1; @@ -121,6 +119,10 @@ static char *next_arg(char *args, char **param, char **val) next = args + i + 1; } else next = args + i; + + /* Chew up trailing spaces. */ + while (*next == ' ') + next++; return next; } @@ -135,6 +137,10 @@ int parse_args(const char *name, DEBUGP("Parsing ARGS: %s\n", args); + /* Chew leading spaces */ + while (*args == ' ') + args++; + while (*args) { int ret; -- cgit v0.10.2 From f4208b9a9538baabad197276076bc1d4f52d42b9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 27 Sep 2005 21:45:35 -0700 Subject: [PATCH] ppc: fix stupid thinko in oprofile fix I did something stupid in my oprofile fix, here's the obvious fix: Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c index 04c1878..22df9a5 100644 --- a/arch/ppc/kernel/perfmon.c +++ b/arch/ppc/kernel/perfmon.c @@ -45,9 +45,8 @@ static void dummy_perf(struct pt_regs *regs) mtpmr(PMRN_PMGC0, pmgc0); } -#elif CONFIG_6xx +#elif defined(CONFIG_6xx) /* Ensure exceptions are disabled */ - static void dummy_perf(struct pt_regs *regs) { unsigned int mmcr0 = mfspr(SPRN_MMCR0); -- cgit v0.10.2 From a9d014afc3609e3094fd06176380ed057edd4a1b Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 27 Sep 2005 21:45:35 -0700 Subject: [PATCH] Add IPMI poweroff control to sysfs Put the IPMI poweroff_powercycle parameter into sysfs. This field is dynamically settable and is valuable to have in sysfs. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index e82a96b..f669477 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -55,7 +55,7 @@ extern void (*pm_power_off)(void); static int poweroff_powercycle; /* parameter definition to allow user to flag power cycle */ -module_param(poweroff_powercycle, int, 0); +module_param(poweroff_powercycle, int, 0644); MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); /* Stuff from the get device id command. */ -- cgit v0.10.2 From 6c132b5fe6579ed4b4892c02fe6c05f7e3afc579 Mon Sep 17 00:00:00 2001 From: john stultz Date: Tue, 27 Sep 2005 21:45:36 -0700 Subject: [PATCH] x86-64: Fix bad assumption that dualcore cpus have synced TSCs This should resolve the issue seen in bugme bug #5105, where it is assumed that dualcore x86_64 systems have synced TSCs. This is not the case, and alternate timesources should be used instead. For more details, see: http://bugzilla.kernel.org/show_bug.cgi?id=5105 Andi's earlier concerns that the TSCs should be synced on dualcore systems have been resolved by confirmation from AMD folks that they can be unsynced. Acked-by: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 2373cb8..703acde 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -959,9 +959,6 @@ static __init int unsynchronized_tsc(void) are handled in the OEM check above. */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) return 0; - /* All in a single socket - should be synchronized */ - if (cpus_weight(cpu_core_map[0]) == num_online_cpus()) - return 0; #endif /* Assume multi socket systems are not synchronized */ return num_online_cpus() > 1; -- cgit v0.10.2 From ed90fb4a19956cece996eb1d26534f592918730e Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Tue, 27 Sep 2005 21:45:37 -0700 Subject: [PATCH] cpuset maintainers Specify the cpuset maintainers. Signed-off-by: Paul Jackson Signed-off-by: Simon Derr Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index 1a0d0c6..c1bc9a8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -604,6 +604,15 @@ P: H. Peter Anvin M: hpa@zytor.com S: Maintained +CPUSETS +P: Paul Jackson +P: Simon Derr +M: pj@sgi.com +M: simon.derr@bull.net +L: linux-kernel@vger.kernel.org +W: http://www.bullopensource.org/cpuset/ +S: Supported + CRAMFS FILESYSTEM W: http://sourceforge.net/projects/cramfs/ S: Orphan -- cgit v0.10.2 From b3ca80935100af47f226be439cb266378dab7bf7 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 27 Sep 2005 21:45:38 -0700 Subject: [PATCH] ppc64: Add missing barrier() in kexec code Mikey and I were testing kexec and hit a lockup. It turns out gcc 4.0 optimises the kexec_prepare_cpus loop so we avoid reloading paca.hw_cpu_id. A gcc barrier() fixes the problem. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index 4775f12..bf7cc4f 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -205,6 +205,7 @@ static void kexec_prepare_cpus(void) continue; while (paca[i].hw_cpu_id != -1) { + barrier(); if (!cpu_possible(i)) { printk("kexec: cpu %d hw_cpu_id %d is not" " possible, ignoring\n", -- cgit v0.10.2 From f65a4d10c8a4eb9f919cf416e5dcd720b7d20f50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 27 Sep 2005 21:45:41 -0700 Subject: [PATCH] orinoco: Fix flood of kernel log with stupid WE warnings Latest wireless extensions moved a field from netdev -> wireless_handlers. The WE core will now printk a warning on every call to get_wireless_stats() on a driver that still uses the old field. This patch fixes orinoco. Signed-off-by: Benjamin Herrenschmidt Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8de49fe..6deb7cc 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card, dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->get_stats = orinoco_get_stats; dev->ethtool_ops = &orinoco_ethtool_ops; - dev->get_wireless_stats = orinoco_get_wireless_stats; dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; dev->change_mtu = orinoco_change_mtu; dev->set_multicast_list = orinoco_set_multicast_list; @@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = { .standard = orinoco_handler, .private = orinoco_private_handler, .private_args = orinoco_privtab, + .get_wireless_stats = orinoco_get_wireless_stats, }; static void orinoco_get_drvinfo(struct net_device *dev, -- cgit v0.10.2 From 0f7347c20c410c300be0db4c132945fd02e54110 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 27 Sep 2005 21:45:43 -0700 Subject: [PATCH] swsusp: avoid problems if there are too many pages to save The following patch makes swsusp avoid problems during resume if there are too many pages to save on suspend. It adds a constant that allows us to verify if we are going to save too many pages and implements the check (this is done as early as we can tell that the check will trigger, which is in swsusp_alloc()). Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/power/power.h b/kernel/power/power.h index 9c9167d..6748de2 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -9,6 +9,9 @@ #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) #endif +#define MAX_PBES ((PAGE_SIZE - sizeof(struct new_utsname) \ + - 4 - 3*sizeof(unsigned long) - sizeof(int) \ + - sizeof(void *)) / sizeof(swp_entry_t)) struct swsusp_info { struct new_utsname uts; @@ -18,7 +21,7 @@ struct swsusp_info { unsigned long image_pages; unsigned long pagedir_pages; suspend_pagedir_t * suspend_pagedir; - swp_entry_t pagedir[768]; + swp_entry_t pagedir[MAX_PBES]; } __attribute__((aligned(PAGE_SIZE))); diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 0dfb249..acf79ac 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -931,6 +931,10 @@ static int swsusp_alloc(void) if (!enough_swap()) return -ENOSPC; + if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE + + !!(nr_copy_pages % PBES_PER_PAGE)) + return -ENOSPC; + if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); return -ENOMEM; -- cgit v0.10.2 From 269fd2a6f84828fd96218d164dace8c413fa5c03 Mon Sep 17 00:00:00 2001 From: "goggin, edward" Date: Tue, 27 Sep 2005 21:45:44 -0700 Subject: [PATCH] device-mapper: Trigger an event when a table is deleted If anything is waiting on a device's table when the device is removed, we must first wake it up so it will release its reference. Otherwise the table's reference count will not drop to zero and the table will not get removed. Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 200a068..54ec737 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi static void __hash_remove(struct hash_cell *hc) { + struct dm_table *table; + /* remove from the dev hash */ list_del(&hc->uuid_list); list_del(&hc->name_list); unregister_with_devfs(hc); dm_set_mdptr(hc->md, NULL); + + table = dm_get_table(hc->md); + if (table) { + dm_table_event(table); + dm_table_put(table); + } + dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); -- cgit v0.10.2 From 485ef69edefd7fc7f351c94d0d77b3ed8a242f7b Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Tue, 27 Sep 2005 21:45:45 -0700 Subject: [PATCH] device-mapper: Fix queue_if_no_path initialisation When creating a multipath device, if the queue_if_no_path parameter is specified it gets ignored. While the queue_if_no_path variable is correctly set to 1, the saved_queue_if_no_path gets set to 0. When the device is subsequently made live (resumed), the saved value (0) always overwrites the live value (1) so the option *always* gets turned off. The fix adds a parameter to the queue_if_no_path() function to indicate whether the previous value should be preserved or not - if not, as when the device is being set up, the saved value is set to the new value (1). Signed-Off-By: Alasdair G Kergon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 785806b..f9b7b32 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, /* * If we run out of usable paths, should we queue I/O or error it? */ -static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path) +static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path, + unsigned save_old_value) { unsigned long flags; spin_lock_irqsave(&m->lock, flags); - m->saved_queue_if_no_path = m->queue_if_no_path; + if (save_old_value) + m->saved_queue_if_no_path = m->queue_if_no_path; + else + m->saved_queue_if_no_path = queue_if_no_path; m->queue_if_no_path = queue_if_no_path; if (!m->queue_if_no_path && m->queue_size) queue_work(kmultipathd, &m->process_queued_ios); @@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m, return 0; if (!strnicmp(shift(as), MESG_STR("queue_if_no_path"))) - return queue_if_no_path(m, 1); + return queue_if_no_path(m, 1, 0); else { ti->error = "Unrecognised multipath feature request"; return -EINVAL; @@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti) { struct multipath *m = (struct multipath *) ti->private; - queue_if_no_path(m, 0); + queue_if_no_path(m, 0, 1); } /* @@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) if (argc == 1) { if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) - return queue_if_no_path(m, 1); + return queue_if_no_path(m, 1, 0); else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) - return queue_if_no_path(m, 0); + return queue_if_no_path(m, 0, 0); } if (argc != 2) -- cgit v0.10.2 From 0f9578b70a9f112bfb541e1d5ab486a376e64503 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 27 Sep 2005 21:45:45 -0700 Subject: [PATCH] ppc64: More hugepage fixes My previous patch fixing invalidation of huge PTEs wasn't good enough, we still had an issue if a PTE invalidation batch contained both small and large pages. This patch fixes this by making sure the batch is flushed if the page size fed to it changes. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c index eb1bbb5..bfd385b 100644 --- a/arch/ppc64/mm/hash_native.c +++ b/arch/ppc64/mm/hash_native.c @@ -343,7 +343,7 @@ static void native_flush_hash_range(unsigned long context, hpte_t *hptep; unsigned long hpte_v; struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long large; + unsigned long large = batch->large; local_irq_save(flags); @@ -356,7 +356,6 @@ static void native_flush_hash_range(unsigned long context, va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); batch->vaddr[j] = va; - large = pte_huge(batch->pte[i]); if (large) vpn = va >> HPAGE_SHIFT; else @@ -406,7 +405,7 @@ static void native_flush_hash_range(unsigned long context, asm volatile("ptesync":::"memory"); for (i = 0; i < j; i++) - __tlbie(batch->vaddr[i], 0); + __tlbie(batch->vaddr[i], large); asm volatile("eieio; tlbsync; ptesync":::"memory"); diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c index d8a6593..21fbffb 100644 --- a/arch/ppc64/mm/tlb.c +++ b/arch/ppc64/mm/tlb.c @@ -143,7 +143,8 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, * up scanning and resetting referenced bits then our batch context * will change mid stream. */ - if (unlikely(i != 0 && context != batch->context)) { + if (i != 0 && (context != batch->context || + batch->large != pte_huge(pte))) { flush_tlb_pending(); i = 0; } @@ -151,6 +152,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, if (i == 0) { batch->context = context; batch->mm = mm; + batch->large = pte_huge(pte); } batch->pte[i] = __pte(pte); batch->addr[i] = addr; diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h index 45411a6..74271d7 100644 --- a/include/asm-ppc64/tlbflush.h +++ b/include/asm-ppc64/tlbflush.h @@ -25,6 +25,7 @@ struct ppc64_tlb_batch { pte_t pte[PPC64_TLB_BATCH_NR]; unsigned long addr[PPC64_TLB_BATCH_NR]; unsigned long vaddr[PPC64_TLB_BATCH_NR]; + unsigned int large; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); -- cgit v0.10.2 From 5c382300876f2337f7b945c159ffcaf285f296ea Mon Sep 17 00:00:00 2001 From: Alok N Kataria Date: Tue, 27 Sep 2005 21:45:46 -0700 Subject: [PATCH] kmalloc_node IRQ safety fix In kmalloc_node we are checking if the allocation is for the same node when interrupts are "on". This may lead to an allocation on another node than intended. This patch just shifts the check for the current node in __cache_alloc_node when interrupts are disabled. Signed-off-by: Alok N Kataria Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/slab.c b/mm/slab.c index c9adfce..5cbbdfa6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2510,16 +2510,12 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep, #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) #endif - -static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) +static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) { - unsigned long save_flags; void* objp; struct array_cache *ac; - cache_alloc_debugcheck_before(cachep, flags); - - local_irq_save(save_flags); + check_irq_off(); ac = ac_data(cachep); if (likely(ac->avail)) { STATS_INC_ALLOCHIT(cachep); @@ -2529,6 +2525,18 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl STATS_INC_ALLOCMISS(cachep); objp = cache_alloc_refill(cachep, flags); } + return objp; +} + +static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) +{ + unsigned long save_flags; + void* objp; + + cache_alloc_debugcheck_before(cachep, flags); + + local_irq_save(save_flags); + objp = ____cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0)); @@ -2856,7 +2864,10 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i cache_alloc_debugcheck_before(cachep, flags); local_irq_save(save_flags); - ptr = __cache_alloc_node(cachep, flags, nodeid); + if (nodeid == numa_node_id()) + ptr = ____cache_alloc(cachep, flags); + else + ptr = __cache_alloc_node(cachep, flags, nodeid); local_irq_restore(save_flags); ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0)); -- cgit v0.10.2 From 5134fc15b643dc36eb9aa77e4318b886844a9ac5 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Wed, 28 Sep 2005 06:42:24 -0700 Subject: [PATCH] cpuset read past eof memory leak fix Don't leak a page of memory if user reads a cpuset file past eof. Signed-off-by: KUROSAWA Takahiro Signed-off-by: Paul Jackson Signed-off-by: Linus Torvalds diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 79866bc..6a6e87b 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -969,7 +969,7 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, ssize_t retval = 0; char *s; char *start; - size_t n; + ssize_t n; if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; @@ -999,12 +999,13 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, *s++ = '\n'; *s = '\0'; - /* Do nothing if *ppos is at the eof or beyond the eof. */ - if (s - page <= *ppos) - return 0; - start = page + *ppos; n = s - start; + + /* Do nothing if *ppos is at the eof or beyond the eof. */ + if (n <= 0) + goto out; + retval = n - copy_to_user(buf, start, min(n, nbytes)); *ppos += retval; out: -- cgit v0.10.2 From 664cceb0093b755739e56572b836a99104ee8a75 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 28 Sep 2005 17:03:15 +0100 Subject: [PATCH] Keys: Add possessor permissions to keys [try #3] The attached patch adds extra permission grants to keys for the possessor of a key in addition to the owner, group and other permissions bits. This makes SUID binaries easier to support without going as far as labelling keys and key targets using the LSM facilities. This patch adds a second "pointer type" to key structures (struct key_ref *) that can have the bottom bit of the address set to indicate the possession of a key. This is propagated through searches from the keyring to the discovered key. It has been made a separate type so that the compiler can spot attempts to dereference a potentially incorrect pointer. The "possession" attribute can't be attached to a key structure directly as it's not an intrinsic property of a key. Pointers to keys have been replaced with struct key_ref *'s wherever possession information needs to be passed through. This does assume that the bottom bit of the pointer will always be zero on return from kmem_cache_alloc(). The key reference type has been made into a typedef so that at least it can be located in the sources, even though it's basically a pointer to an undefined type. I've also renamed the accessor functions to be more useful, and all reference variables should now end in "_ref". Signed-Off-By: David Howells Signed-off-by: Linus Torvalds diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 0321ded..b22e7c8 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -195,8 +195,8 @@ KEY ACCESS PERMISSIONS ====================== Keys have an owner user ID, a group access ID, and a permissions mask. The mask -has up to eight bits each for user, group and other access. Only five of each -set of eight bits are defined. These permissions granted are: +has up to eight bits each for possessor, user, group and other access. Only +five of each set of eight bits are defined. These permissions granted are: (*) View @@ -241,16 +241,16 @@ about the status of the key service: type, description and permissions. The payload of the key is not available this way: - SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY - 00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4 - 00000002 I----- 2 perm 1f0000 0 0 keyring _uid.0: empty - 00000007 I----- 1 perm 1f0000 0 0 keyring _pid.1: empty - 0000018d I----- 1 perm 1f0000 0 0 keyring _pid.412: empty - 000004d2 I--Q-- 1 perm 1f0000 32 -1 keyring _uid.32: 1/4 - 000004d3 I--Q-- 3 perm 1f0000 32 -1 keyring _uid_ses.32: empty - 00000892 I--QU- 1 perm 1f0000 0 0 user metal:copper: 0 - 00000893 I--Q-N 1 35s 1f0000 0 0 user metal:silver: 0 - 00000894 I--Q-- 1 10h 1f0000 0 0 user metal:gold: 0 + SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY + 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4 + 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty + 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty + 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty + 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4 + 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty + 00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0 + 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0 + 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0 The flags are: @@ -637,6 +637,34 @@ call, and the key released upon close. How to deal with conflicting keys due to two different users opening the same file is left to the filesystem author to solve. +Note that there are two different types of pointers to keys that may be +encountered: + + (*) struct key * + + This simply points to the key structure itself. Key structures will be at + least four-byte aligned. + + (*) key_ref_t + + This is equivalent to a struct key *, but the least significant bit is set + if the caller "possesses" the key. By "possession" it is meant that the + calling processes has a searchable link to the key from one of its + keyrings. There are three functions for dealing with these: + + key_ref_t make_key_ref(const struct key *key, + unsigned long possession); + + struct key *key_ref_to_ptr(const key_ref_t key_ref); + + unsigned long is_key_possessed(const key_ref_t key_ref); + + The first function constructs a key reference from a key pointer and + possession information (which must be 0 or 1 and not any other value). + + The second function retrieves the key pointer from a reference and the + third retrieves the possession flag. + When accessing a key's payload contents, certain precautions must be taken to prevent access vs modification races. See the section "Notes on accessing payload contents" for more information. @@ -665,7 +693,11 @@ payload contents" for more information. void key_put(struct key *key); - This can be called from interrupt context. If CONFIG_KEYS is not set then + Or: + + void key_ref_put(key_ref_t key_ref); + + These can be called from interrupt context. If CONFIG_KEYS is not set then the argument will not be parsed. @@ -689,13 +721,17 @@ payload contents" for more information. (*) If a keyring was found in the search, this can be further searched by: - struct key *keyring_search(struct key *keyring, - const struct key_type *type, - const char *description) + key_ref_t keyring_search(key_ref_t keyring_ref, + const struct key_type *type, + const char *description) This searches the keyring tree specified for a matching key. Error ENOKEY - is returned upon failure. If successful, the returned key will need to be - released. + is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful, + the returned key will need to be released. + + The possession attribute from the keyring reference is used to control + access through the permissions mask and is propagated to the returned key + reference pointer if successful. (*) To check the validity of a key, this function can be called: @@ -732,7 +768,7 @@ More complex payload contents must be allocated and a pointer to them set in key->payload.data. One of the following ways must be selected to access the data: - (1) Unmodifyable key type. + (1) Unmodifiable key type. If the key type does not have a modify method, then the key's payload can be accessed without any form of locking, provided that it's known to be diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h index cc32617..918c34a 100644 --- a/include/linux/key-ui.h +++ b/include/linux/key-ui.h @@ -42,11 +42,14 @@ struct keyring_list { /* * check to see whether permission is granted to use a key in the desired way */ -static inline int key_permission(const struct key *key, key_perm_t perm) +static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) { + struct key *key = key_ref_to_ptr(key_ref); key_perm_t kperm; - if (key->uid == current->fsuid) + if (is_key_possessed(key_ref)) + kperm = key->perm >> 24; + else if (key->uid == current->fsuid) kperm = key->perm >> 16; else if (key->gid != -1 && key->perm & KEY_GRP_ALL && @@ -65,11 +68,14 @@ static inline int key_permission(const struct key *key, key_perm_t perm) * check to see whether permission is granted to use a key in at least one of * the desired ways */ -static inline int key_any_permission(const struct key *key, key_perm_t perm) +static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm) { + struct key *key = key_ref_to_ptr(key_ref); key_perm_t kperm; - if (key->uid == current->fsuid) + if (is_key_possessed(key_ref)) + kperm = key->perm >> 24; + else if (key->uid == current->fsuid) kperm = key->perm >> 16; else if (key->gid != -1 && key->perm & KEY_GRP_ALL && @@ -94,13 +100,17 @@ static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) return ret; } -static inline int key_task_permission(const struct key *key, +static inline int key_task_permission(const key_ref_t key_ref, struct task_struct *context, key_perm_t perm) { + struct key *key = key_ref_to_ptr(key_ref); key_perm_t kperm; - if (key->uid == context->fsuid) { + if (is_key_possessed(key_ref)) { + kperm = key->perm >> 24; + } + else if (key->uid == context->fsuid) { kperm = key->perm >> 16; } else if (key->gid != -1 && @@ -121,9 +131,9 @@ static inline int key_task_permission(const struct key *key, } -extern struct key *lookup_user_key(struct task_struct *context, - key_serial_t id, int create, int partial, - key_perm_t perm); +extern key_ref_t lookup_user_key(struct task_struct *context, + key_serial_t id, int create, int partial, + key_perm_t perm); extern long join_session_keyring(const char *name); diff --git a/include/linux/key.h b/include/linux/key.h index 970bbd9..f1efa01 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -35,11 +35,18 @@ struct key; #undef KEY_DEBUGGING -#define KEY_USR_VIEW 0x00010000 /* user can view a key's attributes */ -#define KEY_USR_READ 0x00020000 /* user can read key payload / view keyring */ -#define KEY_USR_WRITE 0x00040000 /* user can update key payload / add link to keyring */ -#define KEY_USR_SEARCH 0x00080000 /* user can find a key in search / search a keyring */ -#define KEY_USR_LINK 0x00100000 /* user can create a link to a key/keyring */ +#define KEY_POS_VIEW 0x01000000 /* possessor can view a key's attributes */ +#define KEY_POS_READ 0x02000000 /* possessor can read key payload / view keyring */ +#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */ +#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */ +#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */ +#define KEY_POS_ALL 0x1f000000 + +#define KEY_USR_VIEW 0x00010000 /* user permissions... */ +#define KEY_USR_READ 0x00020000 +#define KEY_USR_WRITE 0x00040000 +#define KEY_USR_SEARCH 0x00080000 +#define KEY_USR_LINK 0x00100000 #define KEY_USR_ALL 0x001f0000 #define KEY_GRP_VIEW 0x00000100 /* group permissions... */ @@ -67,6 +74,38 @@ struct keyring_name; /*****************************************************************************/ /* + * key reference with possession attribute handling + * + * NOTE! key_ref_t is a typedef'd pointer to a type that is not actually + * defined. This is because we abuse the bottom bit of the reference to carry a + * flag to indicate whether the calling process possesses that key in one of + * its keyrings. + * + * the key_ref_t has been made a separate type so that the compiler can reject + * attempts to dereference it without proper conversion. + * + * the three functions are used to assemble and disassemble references + */ +typedef struct __key_reference_with_attributes *key_ref_t; + +static inline key_ref_t make_key_ref(const struct key *key, + unsigned long possession) +{ + return (key_ref_t) ((unsigned long) key | possession); +} + +static inline struct key *key_ref_to_ptr(const key_ref_t key_ref) +{ + return (struct key *) ((unsigned long) key_ref & ~1UL); +} + +static inline unsigned long is_key_possessed(const key_ref_t key_ref) +{ + return (unsigned long) key_ref & 1UL; +} + +/*****************************************************************************/ +/* * authentication token / access credential / keyring * - types of key include: * - keyrings @@ -215,20 +254,25 @@ static inline struct key *key_get(struct key *key) return key; } +static inline void key_ref_put(key_ref_t key_ref) +{ + key_put(key_ref_to_ptr(key_ref)); +} + extern struct key *request_key(struct key_type *type, const char *description, const char *callout_info); extern int key_validate(struct key *key); -extern struct key *key_create_or_update(struct key *keyring, - const char *type, - const char *description, - const void *payload, - size_t plen, - int not_in_quota); +extern key_ref_t key_create_or_update(key_ref_t keyring, + const char *type, + const char *description, + const void *payload, + size_t plen, + int not_in_quota); -extern int key_update(struct key *key, +extern int key_update(key_ref_t key, const void *payload, size_t plen); @@ -243,9 +287,9 @@ extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, extern int keyring_clear(struct key *keyring); -extern struct key *keyring_search(struct key *keyring, - struct key_type *type, - const char *description); +extern key_ref_t keyring_search(key_ref_t keyring, + struct key_type *type, + const char *description); extern int keyring_add_key(struct key *keyring, struct key *key); @@ -285,6 +329,10 @@ extern void key_init(void); #define key_serial(k) 0 #define key_get(k) ({ NULL; }) #define key_put(k) do { } while(0) +#define key_ref_put(k) do { } while(0) +#define make_key_ref(k) ({ NULL; }) +#define key_ref_to_ptr(k) ({ NULL; }) +#define is_key_possessed(k) 0 #define alloc_uid_keyring(u) 0 #define switch_uid_keyring(u) do { } while(0) #define __install_session_keyring(t, k) ({ NULL; }) diff --git a/security/keys/internal.h b/security/keys/internal.h index 46c8602..db99ed4 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -71,26 +71,26 @@ extern void keyring_publish_name(struct key *keyring); extern int __key_link(struct key *keyring, struct key *key); -extern struct key *__keyring_search_one(struct key *keyring, - const struct key_type *type, - const char *description, - key_perm_t perm); +extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, + const struct key_type *type, + const char *description, + key_perm_t perm); extern struct key *keyring_search_instkey(struct key *keyring, key_serial_t target_id); typedef int (*key_match_func_t)(const struct key *, const void *); -extern struct key *keyring_search_aux(struct key *keyring, - struct task_struct *tsk, - struct key_type *type, - const void *description, - key_match_func_t match); +extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, + struct task_struct *tsk, + struct key_type *type, + const void *description, + key_match_func_t match); -extern struct key *search_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - struct task_struct *tsk); +extern key_ref_t search_process_keyrings(struct key_type *type, + const void *description, + key_match_func_t match, + struct task_struct *tsk); extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); diff --git a/security/keys/key.c b/security/keys/key.c index fb89f98..2182be9 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -693,14 +693,15 @@ void key_type_put(struct key_type *ktype) * - the key has an incremented refcount * - we need to put the key if we get an error */ -static inline struct key *__key_update(struct key *key, const void *payload, - size_t plen) +static inline key_ref_t __key_update(key_ref_t key_ref, + const void *payload, size_t plen) { + struct key *key = key_ref_to_ptr(key_ref); int ret; /* need write permission on the key to update it */ ret = -EACCES; - if (!key_permission(key, KEY_WRITE)) + if (!key_permission(key_ref, KEY_WRITE)) goto error; ret = -EEXIST; @@ -719,12 +720,12 @@ static inline struct key *__key_update(struct key *key, const void *payload, if (ret < 0) goto error; - out: - return key; +out: + return key_ref; - error: +error: key_put(key); - key = ERR_PTR(ret); + key_ref = ERR_PTR(ret); goto out; } /* end __key_update() */ @@ -734,52 +735,56 @@ static inline struct key *__key_update(struct key *key, const void *payload, * search the specified keyring for a key of the same description; if one is * found, update it, otherwise add a new one */ -struct key *key_create_or_update(struct key *keyring, - const char *type, - const char *description, - const void *payload, - size_t plen, - int not_in_quota) +key_ref_t key_create_or_update(key_ref_t keyring_ref, + const char *type, + const char *description, + const void *payload, + size_t plen, + int not_in_quota) { struct key_type *ktype; - struct key *key = NULL; + struct key *keyring, *key = NULL; key_perm_t perm; + key_ref_t key_ref; int ret; - key_check(keyring); - /* look up the key type to see if it's one of the registered kernel * types */ ktype = key_type_lookup(type); if (IS_ERR(ktype)) { - key = ERR_PTR(-ENODEV); + key_ref = ERR_PTR(-ENODEV); goto error; } - ret = -EINVAL; + key_ref = ERR_PTR(-EINVAL); if (!ktype->match || !ktype->instantiate) goto error_2; + keyring = key_ref_to_ptr(keyring_ref); + + key_check(keyring); + + down_write(&keyring->sem); + + /* if we're going to allocate a new key, we're going to have + * to modify the keyring */ + key_ref = ERR_PTR(-EACCES); + if (!key_permission(keyring_ref, KEY_WRITE)) + goto error_3; + /* search for an existing key of the same type and description in the * destination keyring */ - down_write(&keyring->sem); - - key = __keyring_search_one(keyring, ktype, description, 0); - if (!IS_ERR(key)) + key_ref = __keyring_search_one(keyring_ref, ktype, description, 0); + if (!IS_ERR(key_ref)) goto found_matching_key; - /* if we're going to allocate a new key, we're going to have to modify - * the keyring */ - ret = -EACCES; - if (!key_permission(keyring, KEY_WRITE)) - goto error_3; - /* decide on the permissions we want */ - perm = KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; + perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; + perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; if (ktype->read) - perm |= KEY_USR_READ; + perm |= KEY_POS_READ | KEY_USR_READ; if (ktype == &key_type_keyring || ktype->update) perm |= KEY_USR_WRITE; @@ -788,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring, key = key_alloc(ktype, description, current->fsuid, current->fsgid, perm, not_in_quota); if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = ERR_PTR(PTR_ERR(key)); goto error_3; } @@ -796,15 +801,18 @@ struct key *key_create_or_update(struct key *keyring, ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); if (ret < 0) { key_put(key); - key = ERR_PTR(ret); + key_ref = ERR_PTR(ret); + goto error_3; } + key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); + error_3: up_write(&keyring->sem); error_2: key_type_put(ktype); error: - return key; + return key_ref; found_matching_key: /* we found a matching key, so we're going to try to update it @@ -813,7 +821,7 @@ struct key *key_create_or_update(struct key *keyring, up_write(&keyring->sem); key_type_put(ktype); - key = __key_update(key, payload, plen); + key_ref = __key_update(key_ref, payload, plen); goto error; } /* end key_create_or_update() */ @@ -824,15 +832,16 @@ EXPORT_SYMBOL(key_create_or_update); /* * update a key */ -int key_update(struct key *key, const void *payload, size_t plen) +int key_update(key_ref_t key_ref, const void *payload, size_t plen) { + struct key *key = key_ref_to_ptr(key_ref); int ret; key_check(key); /* the key must be writable */ ret = -EACCES; - if (!key_permission(key, KEY_WRITE)) + if (!key_permission(key_ref, KEY_WRITE)) goto error; /* attempt to update it if supported */ diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index a6516a6..4c670ee 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -34,7 +34,7 @@ asmlinkage long sys_add_key(const char __user *_type, size_t plen, key_serial_t ringid) { - struct key *keyring, *key; + key_ref_t keyring_ref, key_ref; char type[32], *description; void *payload; long dlen, ret; @@ -86,25 +86,25 @@ asmlinkage long sys_add_key(const char __user *_type, } /* find the target keyring (which must be writable) */ - keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error3; } /* create or update the requested key and add it to the target * keyring */ - key = key_create_or_update(keyring, type, description, - payload, plen, 0); - if (!IS_ERR(key)) { - ret = key->serial; - key_put(key); + key_ref = key_create_or_update(keyring_ref, type, description, + payload, plen, 0); + if (!IS_ERR(key_ref)) { + ret = key_ref_to_ptr(key_ref)->serial; + key_ref_put(key_ref); } else { - ret = PTR_ERR(key); + ret = PTR_ERR(key_ref); } - key_put(keyring); + key_ref_put(keyring_ref); error3: kfree(payload); error2: @@ -131,7 +131,8 @@ asmlinkage long sys_request_key(const char __user *_type, key_serial_t destringid) { struct key_type *ktype; - struct key *key, *dest; + struct key *key; + key_ref_t dest_ref; char type[32], *description, *callout_info; long dlen, ret; @@ -187,11 +188,11 @@ asmlinkage long sys_request_key(const char __user *_type, } /* get the destination keyring if specified */ - dest = NULL; + dest_ref = NULL; if (destringid) { - dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); - if (IS_ERR(dest)) { - ret = PTR_ERR(dest); + dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); + if (IS_ERR(dest_ref)) { + ret = PTR_ERR(dest_ref); goto error3; } } @@ -204,7 +205,8 @@ asmlinkage long sys_request_key(const char __user *_type, } /* do the search */ - key = request_key_and_link(ktype, description, callout_info, dest); + key = request_key_and_link(ktype, description, callout_info, + key_ref_to_ptr(dest_ref)); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error5; @@ -216,7 +218,7 @@ asmlinkage long sys_request_key(const char __user *_type, error5: key_type_put(ktype); error4: - key_put(dest); + key_ref_put(dest_ref); error3: kfree(callout_info); error2: @@ -234,17 +236,17 @@ asmlinkage long sys_request_key(const char __user *_type, */ long keyctl_get_keyring_ID(key_serial_t id, int create) { - struct key *key; + key_ref_t key_ref; long ret; - key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error; } - ret = key->serial; - key_put(key); + ret = key_ref_to_ptr(key_ref)->serial; + key_ref_put(key_ref); error: return ret; @@ -302,7 +304,7 @@ long keyctl_update_key(key_serial_t id, const void __user *_payload, size_t plen) { - struct key *key; + key_ref_t key_ref; void *payload; long ret; @@ -324,16 +326,16 @@ long keyctl_update_key(key_serial_t id, } /* find the target key (which must be writable) */ - key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error2; } /* update the key */ - ret = key_update(key, payload, plen); + ret = key_update(key_ref, payload, plen); - key_put(key); + key_ref_put(key_ref); error2: kfree(payload); error: @@ -349,19 +351,19 @@ long keyctl_update_key(key_serial_t id, */ long keyctl_revoke_key(key_serial_t id) { - struct key *key; + key_ref_t key_ref; long ret; - key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error; } - key_revoke(key); + key_revoke(key_ref_to_ptr(key_ref)); ret = 0; - key_put(key); + key_ref_put(key_ref); error: return ret; @@ -375,18 +377,18 @@ long keyctl_revoke_key(key_serial_t id) */ long keyctl_keyring_clear(key_serial_t ringid) { - struct key *keyring; + key_ref_t keyring_ref; long ret; - keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error; } - ret = keyring_clear(keyring); + ret = keyring_clear(key_ref_to_ptr(keyring_ref)); - key_put(keyring); + key_ref_put(keyring_ref); error: return ret; @@ -401,26 +403,26 @@ long keyctl_keyring_clear(key_serial_t ringid) */ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) { - struct key *keyring, *key; + key_ref_t keyring_ref, key_ref; long ret; - keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error; } - key = lookup_user_key(NULL, id, 1, 0, KEY_LINK); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 1, 0, KEY_LINK); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error2; } - ret = key_link(keyring, key); + ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); - key_put(key); + key_ref_put(key_ref); error2: - key_put(keyring); + key_ref_put(keyring_ref); error: return ret; @@ -435,26 +437,26 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) */ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) { - struct key *keyring, *key; + key_ref_t keyring_ref, key_ref; long ret; - keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error; } - key = lookup_user_key(NULL, id, 0, 0, 0); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 0, 0, 0); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error2; } - ret = key_unlink(keyring, key); + ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref)); - key_put(key); + key_ref_put(key_ref); error2: - key_put(keyring); + key_ref_put(keyring_ref); error: return ret; @@ -476,24 +478,26 @@ long keyctl_describe_key(key_serial_t keyid, size_t buflen) { struct key *key, *instkey; + key_ref_t key_ref; char *tmpbuf; long ret; - key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); - if (IS_ERR(key)) { + key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); + if (IS_ERR(key_ref)) { /* viewing a key under construction is permitted if we have the * authorisation token handy */ - if (PTR_ERR(key) == -EACCES) { + if (PTR_ERR(key_ref) == -EACCES) { instkey = key_get_instantiation_authkey(keyid); if (!IS_ERR(instkey)) { key_put(instkey); - key = lookup_user_key(NULL, keyid, 0, 1, 0); - if (!IS_ERR(key)) + key_ref = lookup_user_key(NULL, keyid, + 0, 1, 0); + if (!IS_ERR(key_ref)) goto okay; } } - ret = PTR_ERR(key); + ret = PTR_ERR(key_ref); goto error; } @@ -504,13 +508,16 @@ okay: if (!tmpbuf) goto error2; + key = key_ref_to_ptr(key_ref); + ret = snprintf(tmpbuf, PAGE_SIZE - 1, - "%s;%d;%d;%06x;%s", - key->type->name, - key->uid, - key->gid, - key->perm, - key->description ? key->description :"" + "%s;%d;%d;%08x;%s", + key_ref_to_ptr(key_ref)->type->name, + key_ref_to_ptr(key_ref)->uid, + key_ref_to_ptr(key_ref)->gid, + key_ref_to_ptr(key_ref)->perm, + key_ref_to_ptr(key_ref)->description ? + key_ref_to_ptr(key_ref)->description : "" ); /* include a NUL char at the end of the data */ @@ -530,7 +537,7 @@ okay: kfree(tmpbuf); error2: - key_put(key); + key_ref_put(key_ref); error: return ret; @@ -552,7 +559,7 @@ long keyctl_keyring_search(key_serial_t ringid, key_serial_t destringid) { struct key_type *ktype; - struct key *keyring, *key, *dest; + key_ref_t keyring_ref, key_ref, dest_ref; char type[32], *description; long dlen, ret; @@ -581,18 +588,18 @@ long keyctl_keyring_search(key_serial_t ringid, goto error2; /* get the keyring at which to begin the search */ - keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error2; } /* get the destination keyring if specified */ - dest = NULL; + dest_ref = NULL; if (destringid) { - dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); - if (IS_ERR(dest)) { - ret = PTR_ERR(dest); + dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); + if (IS_ERR(dest_ref)) { + ret = PTR_ERR(dest_ref); goto error3; } } @@ -605,9 +612,9 @@ long keyctl_keyring_search(key_serial_t ringid, } /* do the search */ - key = keyring_search(keyring, ktype, description); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = keyring_search(keyring_ref, ktype, description); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); /* treat lack or presence of a negative key the same */ if (ret == -EAGAIN) @@ -616,26 +623,26 @@ long keyctl_keyring_search(key_serial_t ringid, } /* link the resulting key to the destination keyring if we can */ - if (dest) { + if (dest_ref) { ret = -EACCES; - if (!key_permission(key, KEY_LINK)) + if (!key_permission(key_ref, KEY_LINK)) goto error6; - ret = key_link(dest, key); + ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref)); if (ret < 0) goto error6; } - ret = key->serial; + ret = key_ref_to_ptr(key_ref)->serial; error6: - key_put(key); + key_ref_put(key_ref); error5: key_type_put(ktype); error4: - key_put(dest); + key_ref_put(dest_ref); error3: - key_put(keyring); + key_ref_put(keyring_ref); error2: kfree(description); error: @@ -645,16 +652,6 @@ long keyctl_keyring_search(key_serial_t ringid, /*****************************************************************************/ /* - * see if the key we're looking at is the target key - */ -static int keyctl_read_key_same(const struct key *key, const void *target) -{ - return key == target; - -} /* end keyctl_read_key_same() */ - -/*****************************************************************************/ -/* * read a user key's payload * - the keyring must be readable or the key must be searchable from the * process's keyrings @@ -665,38 +662,33 @@ static int keyctl_read_key_same(const struct key *key, const void *target) */ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) { - struct key *key, *skey; + struct key *key; + key_ref_t key_ref; long ret; /* find the key first */ - key = lookup_user_key(NULL, keyid, 0, 0, 0); - if (!IS_ERR(key)) { - /* see if we can read it directly */ - if (key_permission(key, KEY_READ)) - goto can_read_key; - - /* we can't; see if it's searchable from this process's - * keyrings - * - we automatically take account of the fact that it may be - * dangling off an instantiation key - */ - skey = search_process_keyrings(key->type, key, - keyctl_read_key_same, current); - if (!IS_ERR(skey)) - goto can_read_key2; - - ret = PTR_ERR(skey); - if (ret == -EAGAIN) - ret = -EACCES; - goto error2; + key_ref = lookup_user_key(NULL, keyid, 0, 0, 0); + if (IS_ERR(key_ref)) { + ret = -ENOKEY; + goto error; } - ret = -ENOKEY; - goto error; + key = key_ref_to_ptr(key_ref); + + /* see if we can read it directly */ + if (key_permission(key_ref, KEY_READ)) + goto can_read_key; + + /* we can't; see if it's searchable from this process's keyrings + * - we automatically take account of the fact that it may be + * dangling off an instantiation key + */ + if (!is_key_possessed(key_ref)) { + ret = -EACCES; + goto error2; + } /* the key is probably readable - now try to read it */ - can_read_key2: - key_put(skey); can_read_key: ret = key_validate(key); if (ret == 0) { @@ -727,18 +719,21 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) { struct key *key; + key_ref_t key_ref; long ret; ret = 0; if (uid == (uid_t) -1 && gid == (gid_t) -1) goto error; - key = lookup_user_key(NULL, id, 1, 1, 0); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 1, 1, 0); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error; } + key = key_ref_to_ptr(key_ref); + /* make the changes with the locks held to prevent chown/chown races */ ret = -EACCES; down_write(&key->sem); @@ -784,18 +779,21 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) long keyctl_setperm_key(key_serial_t id, key_perm_t perm) { struct key *key; + key_ref_t key_ref; long ret; ret = -EINVAL; - if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) + if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) goto error; - key = lookup_user_key(NULL, id, 1, 1, 0); - if (IS_ERR(key)) { - ret = PTR_ERR(key); + key_ref = lookup_user_key(NULL, id, 1, 1, 0); + if (IS_ERR(key_ref)) { + ret = PTR_ERR(key_ref); goto error; } + key = key_ref_to_ptr(key_ref); + /* make the changes with the locks held to prevent chown/chmod races */ ret = -EACCES; down_write(&key->sem); @@ -824,7 +822,8 @@ long keyctl_instantiate_key(key_serial_t id, key_serial_t ringid) { struct request_key_auth *rka; - struct key *instkey, *keyring; + struct key *instkey; + key_ref_t keyring_ref; void *payload; long ret; @@ -857,21 +856,21 @@ long keyctl_instantiate_key(key_serial_t id, /* find the destination keyring amongst those belonging to the * requesting task */ - keyring = NULL; + keyring_ref = NULL; if (ringid) { - keyring = lookup_user_key(rka->context, ringid, 1, 0, - KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(rka->context, ringid, 1, 0, + KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error3; } } /* instantiate the key and link it into a keyring */ ret = key_instantiate_and_link(rka->target_key, payload, plen, - keyring, instkey); + key_ref_to_ptr(keyring_ref), instkey); - key_put(keyring); + key_ref_put(keyring_ref); error3: key_put(instkey); error2: @@ -889,7 +888,8 @@ long keyctl_instantiate_key(key_serial_t id, long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) { struct request_key_auth *rka; - struct key *instkey, *keyring; + struct key *instkey; + key_ref_t keyring_ref; long ret; /* find the instantiation authorisation key */ @@ -903,19 +903,20 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) /* find the destination keyring if present (which must also be * writable) */ - keyring = NULL; + keyring_ref = NULL; if (ringid) { - keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); - if (IS_ERR(keyring)) { - ret = PTR_ERR(keyring); + keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); + if (IS_ERR(keyring_ref)) { + ret = PTR_ERR(keyring_ref); goto error2; } } /* instantiate the key and link it into a keyring */ - ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey); + ret = key_negate_and_link(rka->target_key, timeout, + key_ref_to_ptr(keyring_ref), instkey); - key_put(keyring); + key_ref_put(keyring_ref); error2: key_put(instkey); error: diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 9c208c7..0639396 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -309,7 +309,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, int ret; keyring = key_alloc(&key_type_keyring, description, - uid, gid, KEY_USR_ALL, not_in_quota); + uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota); if (!IS_ERR(keyring)) { ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); @@ -333,12 +333,13 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, * - we rely on RCU to prevent the keyring lists from disappearing on us * - we return -EAGAIN if we didn't find any matching key * - we return -ENOKEY if we only found negative matching keys + * - we propagate the possession attribute from the keyring ref to the key ref */ -struct key *keyring_search_aux(struct key *keyring, - struct task_struct *context, - struct key_type *type, - const void *description, - key_match_func_t match) +key_ref_t keyring_search_aux(key_ref_t keyring_ref, + struct task_struct *context, + struct key_type *type, + const void *description, + key_match_func_t match) { struct { struct keyring_list *keylist; @@ -347,29 +348,33 @@ struct key *keyring_search_aux(struct key *keyring, struct keyring_list *keylist; struct timespec now; - struct key *key; + unsigned long possessed; + struct key *keyring, *key; + key_ref_t key_ref; long err; int sp, kix; + keyring = key_ref_to_ptr(keyring_ref); + possessed = is_key_possessed(keyring_ref); key_check(keyring); - rcu_read_lock(); - /* top keyring must have search permission to begin the search */ - key = ERR_PTR(-EACCES); - if (!key_task_permission(keyring, context, KEY_SEARCH)) + key_ref = ERR_PTR(-EACCES); + if (!key_task_permission(keyring_ref, context, KEY_SEARCH)) goto error; - key = ERR_PTR(-ENOTDIR); + key_ref = ERR_PTR(-ENOTDIR); if (keyring->type != &key_type_keyring) goto error; + rcu_read_lock(); + now = current_kernel_time(); err = -EAGAIN; sp = 0; /* start processing a new keyring */ - descend: +descend: if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) goto not_this_keyring; @@ -397,7 +402,8 @@ struct key *keyring_search_aux(struct key *keyring, continue; /* key must have search permissions */ - if (!key_task_permission(key, context, KEY_SEARCH)) + if (!key_task_permission(make_key_ref(key, possessed), + context, KEY_SEARCH)) continue; /* we set a different error code if we find a negative key */ @@ -411,7 +417,7 @@ struct key *keyring_search_aux(struct key *keyring, /* search through the keyrings nested in this one */ kix = 0; - ascend: +ascend: for (; kix < keylist->nkeys; kix++) { key = keylist->keys[kix]; if (key->type != &key_type_keyring) @@ -423,7 +429,8 @@ struct key *keyring_search_aux(struct key *keyring, if (sp >= KEYRING_SEARCH_MAX_DEPTH) continue; - if (!key_task_permission(key, context, KEY_SEARCH)) + if (!key_task_permission(make_key_ref(key, possessed), + context, KEY_SEARCH)) continue; /* stack the current position */ @@ -438,7 +445,7 @@ struct key *keyring_search_aux(struct key *keyring, /* the keyring we're looking at was disqualified or didn't contain a * matching key */ - not_this_keyring: +not_this_keyring: if (sp > 0) { /* resume the processing of a keyring higher up in the tree */ sp--; @@ -447,16 +454,18 @@ struct key *keyring_search_aux(struct key *keyring, goto ascend; } - key = ERR_PTR(err); - goto error; + key_ref = ERR_PTR(err); + goto error_2; /* we found a viable match */ - found: +found: atomic_inc(&key->usage); key_check(key); - error: + key_ref = make_key_ref(key, possessed); +error_2: rcu_read_unlock(); - return key; +error: + return key_ref; } /* end keyring_search_aux() */ @@ -469,9 +478,9 @@ struct key *keyring_search_aux(struct key *keyring, * - we return -EAGAIN if we didn't find any matching key * - we return -ENOKEY if we only found negative matching keys */ -struct key *keyring_search(struct key *keyring, - struct key_type *type, - const char *description) +key_ref_t keyring_search(key_ref_t keyring, + struct key_type *type, + const char *description) { if (!type->match) return ERR_PTR(-ENOKEY); @@ -488,15 +497,19 @@ EXPORT_SYMBOL(keyring_search); * search the given keyring only (no recursion) * - keyring must be locked by caller */ -struct key *__keyring_search_one(struct key *keyring, - const struct key_type *ktype, - const char *description, - key_perm_t perm) +key_ref_t __keyring_search_one(key_ref_t keyring_ref, + const struct key_type *ktype, + const char *description, + key_perm_t perm) { struct keyring_list *klist; - struct key *key; + unsigned long possessed; + struct key *keyring, *key; int loop; + keyring = key_ref_to_ptr(keyring_ref); + possessed = is_key_possessed(keyring_ref); + rcu_read_lock(); klist = rcu_dereference(keyring->payload.subscriptions); @@ -507,21 +520,21 @@ struct key *__keyring_search_one(struct key *keyring, if (key->type == ktype && (!key->type->match || key->type->match(key, description)) && - key_permission(key, perm) && + key_permission(make_key_ref(key, possessed), + perm) && !test_bit(KEY_FLAG_REVOKED, &key->flags) ) goto found; } } - key = ERR_PTR(-ENOKEY); - goto error; + rcu_read_unlock(); + return ERR_PTR(-ENOKEY); found: atomic_inc(&key->usage); - error: rcu_read_unlock(); - return key; + return make_key_ref(key, possessed); } /* end __keyring_search_one() */ @@ -603,7 +616,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) if (strcmp(keyring->description, name) != 0) continue; - if (!key_permission(keyring, KEY_SEARCH)) + if (!key_permission(make_key_ref(keyring, 0), + KEY_SEARCH)) continue; /* found a potential candidate, but we still need to diff --git a/security/keys/proc.c b/security/keys/proc.c index c55cf1f..12b750e 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -167,7 +167,7 @@ static int proc_keys_show(struct seq_file *m, void *v) #define showflag(KEY, LETTER, FLAG) \ (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') - seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", + seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", key->serial, showflag(key, 'I', KEY_FLAG_INSTANTIATED), showflag(key, 'R', KEY_FLAG_REVOKED), diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index c089f78..d42d215 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -39,7 +39,7 @@ struct key root_user_keyring = { .type = &key_type_keyring, .user = &root_key_user, .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), - .perm = KEY_USR_ALL, + .perm = KEY_POS_ALL | KEY_USR_ALL, .flags = 1 << KEY_FLAG_INSTANTIATED, .description = "_uid.0", #ifdef KEY_DEBUGGING @@ -54,7 +54,7 @@ struct key root_session_keyring = { .type = &key_type_keyring, .user = &root_key_user, .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), - .perm = KEY_USR_ALL, + .perm = KEY_POS_ALL | KEY_USR_ALL, .flags = 1 << KEY_FLAG_INSTANTIATED, .description = "_uid_ses.0", #ifdef KEY_DEBUGGING @@ -98,7 +98,7 @@ int alloc_uid_keyring(struct user_struct *user) user->session_keyring = session_keyring; ret = 0; - error: +error: return ret; } /* end alloc_uid_keyring() */ @@ -156,7 +156,7 @@ int install_thread_keyring(struct task_struct *tsk) ret = 0; key_put(old); - error: +error: return ret; } /* end install_thread_keyring() */ @@ -193,7 +193,7 @@ int install_process_keyring(struct task_struct *tsk) } ret = 0; - error: +error: return ret; } /* end install_process_keyring() */ @@ -236,7 +236,7 @@ static int install_session_keyring(struct task_struct *tsk, /* we're using RCU on the pointer */ synchronize_rcu(); key_put(old); - error: +error: return ret; } /* end install_session_keyring() */ @@ -376,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk) * - we return -EAGAIN if we didn't find any matching key * - we return -ENOKEY if we found only negative matching keys */ -struct key *search_process_keyrings(struct key_type *type, - const void *description, - key_match_func_t match, - struct task_struct *context) +key_ref_t search_process_keyrings(struct key_type *type, + const void *description, + key_match_func_t match, + struct task_struct *context) { struct request_key_auth *rka; - struct key *key, *ret, *err, *instkey; + key_ref_t key_ref, ret, err, instkey_ref; /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were * searchable, but we failed to find a key or we found a negative key; @@ -391,46 +391,48 @@ struct key *search_process_keyrings(struct key_type *type, * * in terms of priority: success > -ENOKEY > -EAGAIN > other error */ - key = NULL; + key_ref = NULL; ret = NULL; err = ERR_PTR(-EAGAIN); /* search the thread keyring first */ if (context->thread_keyring) { - key = keyring_search_aux(context->thread_keyring, - context, type, description, match); - if (!IS_ERR(key)) + key_ref = keyring_search_aux( + make_key_ref(context->thread_keyring, 1), + context, type, description, match); + if (!IS_ERR(key_ref)) goto found; - switch (PTR_ERR(key)) { + switch (PTR_ERR(key_ref)) { case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ - ret = key; + ret = key_ref; break; default: - err = key; + err = key_ref; break; } } /* search the process keyring second */ if (context->signal->process_keyring) { - key = keyring_search_aux(context->signal->process_keyring, - context, type, description, match); - if (!IS_ERR(key)) + key_ref = keyring_search_aux( + make_key_ref(context->signal->process_keyring, 1), + context, type, description, match); + if (!IS_ERR(key_ref)) goto found; - switch (PTR_ERR(key)) { + switch (PTR_ERR(key_ref)) { case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ - ret = key; + ret = key_ref; break; default: - err = key; + err = key_ref; break; } } @@ -438,23 +440,25 @@ struct key *search_process_keyrings(struct key_type *type, /* search the session keyring */ if (context->signal->session_keyring) { rcu_read_lock(); - key = keyring_search_aux( - rcu_dereference(context->signal->session_keyring), + key_ref = keyring_search_aux( + make_key_ref(rcu_dereference( + context->signal->session_keyring), + 1), context, type, description, match); rcu_read_unlock(); - if (!IS_ERR(key)) + if (!IS_ERR(key_ref)) goto found; - switch (PTR_ERR(key)) { + switch (PTR_ERR(key_ref)) { case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ - ret = key; + ret = key_ref; break; default: - err = key; + err = key_ref; break; } @@ -465,51 +469,54 @@ struct key *search_process_keyrings(struct key_type *type, goto no_key; rcu_read_lock(); - instkey = __keyring_search_one( - rcu_dereference(context->signal->session_keyring), + instkey_ref = __keyring_search_one( + make_key_ref(rcu_dereference( + context->signal->session_keyring), + 1), &key_type_request_key_auth, NULL, 0); rcu_read_unlock(); - if (IS_ERR(instkey)) + if (IS_ERR(instkey_ref)) goto no_key; - rka = instkey->payload.data; + rka = key_ref_to_ptr(instkey_ref)->payload.data; - key = search_process_keyrings(type, description, match, - rka->context); - key_put(instkey); + key_ref = search_process_keyrings(type, description, match, + rka->context); + key_ref_put(instkey_ref); - if (!IS_ERR(key)) + if (!IS_ERR(key_ref)) goto found; - switch (PTR_ERR(key)) { + switch (PTR_ERR(key_ref)) { case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ - ret = key; + ret = key_ref; break; default: - err = key; + err = key_ref; break; } } /* or search the user-session keyring */ else { - key = keyring_search_aux(context->user->session_keyring, - context, type, description, match); - if (!IS_ERR(key)) + key_ref = keyring_search_aux( + make_key_ref(context->user->session_keyring, 1), + context, type, description, match); + if (!IS_ERR(key_ref)) goto found; - switch (PTR_ERR(key)) { + switch (PTR_ERR(key_ref)) { case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ - ret = key; + ret = key_ref; break; default: - err = key; + err = key_ref; break; } } @@ -517,29 +524,40 @@ struct key *search_process_keyrings(struct key_type *type, no_key: /* no key - decide on the error we're going to go for */ - key = ret ? ret : err; + key_ref = ret ? ret : err; found: - return key; + return key_ref; } /* end search_process_keyrings() */ /*****************************************************************************/ /* + * see if the key we're looking at is the target key + */ +static int lookup_user_key_possessed(const struct key *key, const void *target) +{ + return key == target; + +} /* end lookup_user_key_possessed() */ + +/*****************************************************************************/ +/* * lookup a key given a key ID from userspace with a given permissions mask * - don't create special keyrings unless so requested * - partially constructed keys aren't found unless requested */ -struct key *lookup_user_key(struct task_struct *context, key_serial_t id, - int create, int partial, key_perm_t perm) +key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, + int create, int partial, key_perm_t perm) { + key_ref_t key_ref, skey_ref; struct key *key; int ret; if (!context) context = current; - key = ERR_PTR(-ENOKEY); + key_ref = ERR_PTR(-ENOKEY); switch (id) { case KEY_SPEC_THREAD_KEYRING: @@ -556,6 +574,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, key = context->thread_keyring; atomic_inc(&key->usage); + key_ref = make_key_ref(key, 1); break; case KEY_SPEC_PROCESS_KEYRING: @@ -572,6 +591,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, key = context->signal->process_keyring; atomic_inc(&key->usage); + key_ref = make_key_ref(key, 1); break; case KEY_SPEC_SESSION_KEYRING: @@ -579,7 +599,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, /* always install a session keyring upon access if one * doesn't exist yet */ ret = install_session_keyring( - context, context->user->session_keyring); + context, context->user->session_keyring); if (ret < 0) goto error; } @@ -588,16 +608,19 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, key = rcu_dereference(context->signal->session_keyring); atomic_inc(&key->usage); rcu_read_unlock(); + key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_KEYRING: key = context->user->uid_keyring; atomic_inc(&key->usage); + key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_SESSION_KEYRING: key = context->user->session_keyring; atomic_inc(&key->usage); + key_ref = make_key_ref(key, 1); break; case KEY_SPEC_GROUP_KEYRING: @@ -606,13 +629,28 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, goto error; default: - key = ERR_PTR(-EINVAL); + key_ref = ERR_PTR(-EINVAL); if (id < 1) goto error; key = key_lookup(id); - if (IS_ERR(key)) + if (IS_ERR(key)) { + key_ref = ERR_PTR(PTR_ERR(key)); goto error; + } + + key_ref = make_key_ref(key, 0); + + /* check to see if we possess the key */ + skey_ref = search_process_keyrings(key->type, key, + lookup_user_key_possessed, + current); + + if (!IS_ERR(skey_ref)) { + key_put(key); + key_ref = skey_ref; + } + break; } @@ -630,15 +668,15 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id, /* check the permissions */ ret = -EACCES; - if (!key_task_permission(key, context, perm)) + if (!key_task_permission(key_ref, context, perm)) goto invalid_key; - error: - return key; +error: + return key_ref; - invalid_key: - key_put(key); - key = ERR_PTR(ret); +invalid_key: + key_ref_put(key_ref); + key_ref = ERR_PTR(ret); goto error; } /* end lookup_user_key() */ @@ -694,9 +732,9 @@ long join_session_keyring(const char *name) ret = keyring->serial; key_put(keyring); - error2: +error2: up(&key_session_sem); - error: +error: return ret; } /* end join_session_keyring() */ diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 90c1506..e6dd366 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -129,7 +129,7 @@ static struct key *__request_key_construction(struct key_type *type, /* create a key and add it to the queue */ key = key_alloc(type, description, - current->fsuid, current->fsgid, KEY_USR_ALL, 0); + current->fsuid, current->fsgid, KEY_POS_ALL, 0); if (IS_ERR(key)) goto alloc_failed; @@ -365,14 +365,24 @@ struct key *request_key_and_link(struct key_type *type, { struct key_user *user; struct key *key; + key_ref_t key_ref; kenter("%s,%s,%s,%p", type->name, description, callout_info, dest_keyring); /* search all the process keyrings for a key */ - key = search_process_keyrings(type, description, type->match, current); + key_ref = search_process_keyrings(type, description, type->match, + current); - if (PTR_ERR(key) == -EAGAIN) { + kdebug("search 1: %p", key_ref); + + if (!IS_ERR(key_ref)) { + key = key_ref_to_ptr(key_ref); + } + else if (PTR_ERR(key_ref) != -EAGAIN) { + key = ERR_PTR(PTR_ERR(key_ref)); + } + else { /* the search failed, but the keyrings were searchable, so we * should consult userspace if we can */ key = ERR_PTR(-ENOKEY); @@ -384,7 +394,7 @@ struct key *request_key_and_link(struct key_type *type, if (!user) goto nomem; - do { + for (;;) { if (signal_pending(current)) goto interrupted; @@ -397,10 +407,22 @@ struct key *request_key_and_link(struct key_type *type, /* someone else made the key we want, so we need to * search again as it might now be available to us */ - key = search_process_keyrings(type, description, - type->match, current); + key_ref = search_process_keyrings(type, description, + type->match, + current); + + kdebug("search 2: %p", key_ref); - } while (PTR_ERR(key) == -EAGAIN); + if (!IS_ERR(key_ref)) { + key = key_ref_to_ptr(key_ref); + break; + } + + if (PTR_ERR(key_ref) != -EAGAIN) { + key = ERR_PTR(PTR_ERR(key_ref)); + break; + } + } key_user_put(user); diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index f222646..1ecd3d3 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -126,7 +126,7 @@ struct key *request_key_auth_new(struct key *target, struct key **_rkakey) rkakey = key_alloc(&key_type_request_key_auth, desc, current->fsuid, current->fsgid, - KEY_USR_VIEW, 1); + KEY_POS_VIEW | KEY_USR_VIEW, 1); if (IS_ERR(rkakey)) { key_put(keyring); kleave("= %ld", PTR_ERR(rkakey)); -- cgit v0.10.2 From 1146bc743e074760ef0dd08b3457f35a68069a54 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 28 Sep 2005 19:28:37 +0200 Subject: [PATCH] pcmcia: allow one port excludes Allow for excluding only one port in /etc/pcmcia/config.otps Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index c42455d..7e1b7fc 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -691,7 +691,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned unsigned long size = end - start + 1; int ret = 0; - if (end <= start) + if (end < start) return -EINVAL; down(&rsrc_sem); @@ -724,7 +724,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long unsigned long size = end - start + 1; int ret = 0; - if (end <= start) + if (end < start) return -EINVAL; if (end > IO_SPACE_LIMIT) @@ -925,7 +925,7 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size return -EINVAL; } } - if (end_addr <= start_addr) + if (end_addr < start_addr) return -EINVAL; ret = adjust_io(s, add, start_addr, end_addr); @@ -977,7 +977,7 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz return -EINVAL; } } - if (end_addr <= start_addr) + if (end_addr < start_addr) return -EINVAL; ret = adjust_memory(s, add, start_addr, end_addr); -- cgit v0.10.2 From 54bb5675a6e966a58755ac44e3407f8ec2272b82 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 28 Sep 2005 19:29:59 +0200 Subject: [PATCH] pcmcia: only start up nonstatic sockets if both mem and io are available Only start up nonstatic sockets if both IO and MEM resources are available. Thanks to Russell King and Matthew Wilcox for tracking this down. Signed-off-by: Dominik Brodowski diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 7e1b7fc..f9a5c70 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -817,7 +817,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) /* if we got at least one of IO, and one of MEM, we can be glad and * activate the PCMCIA subsystem */ - if (done & (IORESOURCE_MEM | IORESOURCE_IO)) + if (done == (IORESOURCE_MEM | IORESOURCE_IO)) s->resource_setup_done = 1; return 0; -- cgit v0.10.2 From 6b251858d377196b8cea20e65cae60f584a42735 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 16:31:48 -0700 Subject: [TCP]: Fix init_cwnd calculations in tcp_select_initial_window() Match it up to what RFC2414 really specifies. Noticed by Rick Jones. Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d6e3d26..caf2e2c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -190,15 +190,16 @@ void tcp_select_initial_window(int __space, __u32 mss, } /* Set initial window to value enough for senders, - * following RFC1414. Senders, not following this RFC, + * following RFC2414. Senders, not following this RFC, * will be satisfied with 2. */ if (mss > (1<<*rcv_wscale)) { - int init_cwnd = 4; - if (mss > 1460*3) + int init_cwnd; + + if (mss > 1460) init_cwnd = 2; - else if (mss > 1460) - init_cwnd = 3; + else + init_cwnd = (mss > 1095) ? 3 : 4; if (*rcv_wnd > init_cwnd*mss) *rcv_wnd = init_cwnd*mss; } -- cgit v0.10.2 From e2c4b72158a9f1286df41dee478e774f1b94e93a Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Wed, 28 Sep 2005 16:34:24 -0700 Subject: [ATM]: net/atm/ioctl.c: autoload pppoatm and br2684 Signed-off-by: Roman Kagan Signed-off-by: Chas Williams diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index d89056e..a150198 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -105,17 +105,35 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (!error) sock->state = SS_CONNECTED; goto done; - default: + case ATM_SETBACKEND: + case ATM_NEWBACKENDIF: + { + atm_backend_t backend; + error = get_user(backend, (atm_backend_t __user *) argp); + if (error) + goto done; + switch (backend) { + case ATM_BACKEND_PPP: + request_module("pppoatm"); + break; + case ATM_BACKEND_BR2684: + request_module("br2684"); + break; + } + } + break; + case ATMMPC_CTRL: + case ATMMPC_DATA: + request_module("mpoa"); + break; + case ATMARPD_CTRL: + request_module("clip"); + break; + case ATMLEC_CTRL: + request_module("lec"); break; } - if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA) - request_module("mpoa"); - if (cmd == ATMARPD_CTRL) - request_module("clip"); - if (cmd == ATMLEC_CTRL) - request_module("lec"); - error = -ENOIOCTLCMD; down(&ioctl_mutex); -- cgit v0.10.2 From 9301e320e98ff19a0e48881b038d0c24ca76e6c0 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Wed, 28 Sep 2005 16:35:01 -0700 Subject: [ATM]: track and close listen sockets when sigd exits Signed-off-by: Chas Williams diff --git a/net/atm/common.c b/net/atm/common.c index e93e838..801a581 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -178,8 +178,6 @@ static void vcc_destroy_socket(struct sock *sk) if (vcc->push) vcc->push(vcc, NULL); /* atmarpd has no push */ - vcc_remove_socket(sk); /* no more receive */ - while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { atm_return(vcc,skb->truesize); kfree_skb(skb); @@ -188,6 +186,8 @@ static void vcc_destroy_socket(struct sock *sk) module_put(vcc->dev->ops->owner); atm_dev_put(vcc->dev); } + + vcc_remove_socket(sk); } diff --git a/net/atm/signaling.c b/net/atm/signaling.c index f7c449a..e7211a7 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -217,8 +217,9 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, static void purge_vcc(struct atm_vcc *vcc) { if (sk_atm(vcc)->sk_family == PF_ATMSVC && - !test_bit(ATM_VF_META,&vcc->flags)) { - set_bit(ATM_VF_RELEASED,&vcc->flags); + !test_bit(ATM_VF_META, &vcc->flags)) { + set_bit(ATM_VF_RELEASED, &vcc->flags); + clear_bit(ATM_VF_REGIS, &vcc->flags); vcc_release_async(vcc, -EUNATCH); } } @@ -243,8 +244,7 @@ static void sigd_close(struct atm_vcc *vcc) sk_for_each(s, node, head) { struct atm_vcc *vcc = atm_sk(s); - if (vcc->dev) - purge_vcc(vcc); + purge_vcc(vcc); } } read_unlock(&vcc_sklist_lock); diff --git a/net/atm/svc.c b/net/atm/svc.c index 08e4605..d7b2661 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -302,6 +302,7 @@ static int svc_listen(struct socket *sock,int backlog) error = -EINVAL; goto out; } + vcc_insert_socket(sk); set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); -- cgit v0.10.2 From 735631a9196db42631b8817892605ee72e13a58b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 28 Sep 2005 16:35:22 -0700 Subject: [ATM]: fix bug in atm address list handling From: Martin Whitaker Signed-off-by: Chas Williams diff --git a/net/atm/addr.c b/net/atm/addr.c index 1c8867f..a30d0bf 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -50,8 +50,10 @@ void atm_reset_addr(struct atm_dev *dev) struct atm_dev_addr *this, *p; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry_safe(this, p, &dev->local, entry) - kfree(this); + list_for_each_entry_safe(this, p, &dev->local, entry) { + list_del(&this->entry); + kfree(this); + } spin_unlock_irqrestore(&dev->lock, flags); notify_sigd(dev); } -- cgit v0.10.2 From 705747ab87c96f1b4b8e73ba617c323d9087f6ac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 16:48:40 -0700 Subject: [SPARC64]: Fix bug in unaligned load endianness swapping The in-memory value was being swapped, not the value we loaded into the register. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 42718f6..02af08f 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -294,7 +294,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u kernel_mna_trap_fault(); } else { - unsigned long addr; + unsigned long addr, *reg_addr; int orig_asi, asi; addr = compute_effective_address(regs, insn, @@ -319,11 +319,11 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u }; switch (dir) { case load: - do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), - size, (unsigned long *) addr, + reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); + do_int_load(reg_addr, size, (unsigned long *) addr, decode_signedness(insn), asi); if (unlikely(asi != orig_asi)) { - unsigned long val_in = *(unsigned long *) addr; + unsigned long val_in = *reg_addr; switch (size) { case 2: val_in = swab16(val_in); @@ -339,7 +339,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u BUG(); break; }; - *(unsigned long *) addr = val_in; + *reg_addr = val_in; } break; -- cgit v0.10.2 From d70ed6075f15bdbb0548d162394bf10332769c88 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 28 Sep 2005 19:56:57 -0700 Subject: [IPoIB] Rename IPoIB's path_lookup() to avoid name clashes Rename IPoIB driver's path_lookup() to ipoib_path_lookup() to avoid a clashes with the kernel global path_lookup(). We don't hit this with the current kernel source, but some external patches seem to trigger this, and it's cleaner to avoid clashing with global names anyway. Signed-off-by: Roland Dreier refs/heads/for-linus diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 704f48e..6c5bf07 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -474,7 +474,7 @@ err: spin_unlock(&priv->lock); } -static void path_lookup(struct sk_buff *skb, struct net_device *dev) +static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(skb->dev); @@ -569,7 +569,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->dst && skb->dst->neighbour) { if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { - path_lookup(skb, dev); + ipoib_path_lookup(skb, dev); goto out; } -- cgit v0.10.2 From 8cf14af0a740fb7e9f94a203b5a989beb875d58f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 20:21:11 -0700 Subject: [SPARC64]: Convert to use generic exception table support. The funny "range" exception table entries we had were only used by the compat layer socketcall assembly, and it wasn't even needed there. For free we now get proper exception table sorting and fast binary searching. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 5f9e4fa..4fb99e0 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -158,163 +158,163 @@ sys32_socketcall: /* %o0=call, %o1=args */ jmpl %g2 + %o0, %g0 nop - /* Each entry is exactly 32 bytes. */ .align 32 __socketcall_table_begin: + + /* Each entry is exactly 32 bytes. */ do_sys_socket: /* sys_socket(int, int, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +1: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_socket), %g1 - ldswa [%o1 + 0x8] %asi, %o2 +2: ldswa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_socket), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +3: ldswa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +4: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_bind), %g1 - ldswa [%o1 + 0x8] %asi, %o2 +5: ldswa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_bind), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +6: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +7: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_connect), %g1 - ldswa [%o1 + 0x8] %asi, %o2 +8: ldswa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_connect), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +9: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_listen: /* sys_listen(int, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +10: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_listen), %g1 jmpl %g1 + %lo(sys_listen), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +11: ldswa [%o1 + 0x4] %asi, %o1 nop nop nop nop do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ - ldswa [%o1 + 0x0] %asi, %o0 +12: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_accept), %g1 - lduwa [%o1 + 0x8] %asi, %o2 +13: lduwa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_accept), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +14: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ - ldswa [%o1 + 0x0] %asi, %o0 +15: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_getsockname), %g1 - lduwa [%o1 + 0x8] %asi, %o2 +16: lduwa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_getsockname), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +17: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ - ldswa [%o1 + 0x0] %asi, %o0 +18: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_getpeername), %g1 - lduwa [%o1 + 0x8] %asi, %o2 +19: lduwa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(sys_getpeername), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +20: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ - ldswa [%o1 + 0x0] %asi, %o0 +21: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_socketpair), %g1 - ldswa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 +22: ldswa [%o1 + 0x8] %asi, %o2 +23: lduwa [%o1 + 0xc] %asi, %o3 jmpl %g1 + %lo(sys_socketpair), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +24: ldswa [%o1 + 0x4] %asi, %o1 nop nop do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ - ldswa [%o1 + 0x0] %asi, %o0 +25: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_send), %g1 - lduwa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 +26: lduwa [%o1 + 0x8] %asi, %o2 +27: lduwa [%o1 + 0xc] %asi, %o3 jmpl %g1 + %lo(sys_send), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +28: lduwa [%o1 + 0x4] %asi, %o1 nop nop do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ - ldswa [%o1 + 0x0] %asi, %o0 +29: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_recv), %g1 - lduwa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 +30: lduwa [%o1 + 0x8] %asi, %o2 +31: lduwa [%o1 + 0xc] %asi, %o3 jmpl %g1 + %lo(sys_recv), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +32: lduwa [%o1 + 0x4] %asi, %o1 nop nop do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +33: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_sendto), %g1 - lduwa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 - lduwa [%o1 + 0x10] %asi, %o4 - ldswa [%o1 + 0x14] %asi, %o5 +34: lduwa [%o1 + 0x8] %asi, %o2 +35: lduwa [%o1 + 0xc] %asi, %o3 +36: lduwa [%o1 + 0x10] %asi, %o4 +37: ldswa [%o1 + 0x14] %asi, %o5 jmpl %g1 + %lo(sys_sendto), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +38: lduwa [%o1 + 0x4] %asi, %o1 do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ - ldswa [%o1 + 0x0] %asi, %o0 +39: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_recvfrom), %g1 - lduwa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 - lduwa [%o1 + 0x10] %asi, %o4 - lduwa [%o1 + 0x14] %asi, %o5 +40: lduwa [%o1 + 0x8] %asi, %o2 +41: lduwa [%o1 + 0xc] %asi, %o3 +42: lduwa [%o1 + 0x10] %asi, %o4 +43: lduwa [%o1 + 0x14] %asi, %o5 jmpl %g1 + %lo(sys_recvfrom), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +44: lduwa [%o1 + 0x4] %asi, %o1 do_sys_shutdown: /* sys_shutdown(int, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +45: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(sys_shutdown), %g1 jmpl %g1 + %lo(sys_shutdown), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +46: ldswa [%o1 + 0x4] %asi, %o1 nop nop nop nop do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ - ldswa [%o1 + 0x0] %asi, %o0 +47: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(compat_sys_setsockopt), %g1 - ldswa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 - ldswa [%o1 + 0x10] %asi, %o4 +48: ldswa [%o1 + 0x8] %asi, %o2 +49: lduwa [%o1 + 0xc] %asi, %o3 +50: ldswa [%o1 + 0x10] %asi, %o4 jmpl %g1 + %lo(compat_sys_setsockopt), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +51: ldswa [%o1 + 0x4] %asi, %o1 nop do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ - ldswa [%o1 + 0x0] %asi, %o0 +52: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(compat_sys_getsockopt), %g1 - ldswa [%o1 + 0x8] %asi, %o2 - lduwa [%o1 + 0xc] %asi, %o3 - lduwa [%o1 + 0x10] %asi, %o4 +53: ldswa [%o1 + 0x8] %asi, %o2 +54: lduwa [%o1 + 0xc] %asi, %o3 +55: lduwa [%o1 + 0x10] %asi, %o4 jmpl %g1 + %lo(compat_sys_getsockopt), %g0 - ldswa [%o1 + 0x4] %asi, %o1 +56: ldswa [%o1 + 0x4] %asi, %o1 nop do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ - ldswa [%o1 + 0x0] %asi, %o0 +57: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(compat_sys_sendmsg), %g1 - lduwa [%o1 + 0x8] %asi, %o2 +58: lduwa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(compat_sys_sendmsg), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +59: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ - ldswa [%o1 + 0x0] %asi, %o0 +60: ldswa [%o1 + 0x0] %asi, %o0 sethi %hi(compat_sys_recvmsg), %g1 - lduwa [%o1 + 0x8] %asi, %o2 +61: lduwa [%o1 + 0x8] %asi, %o2 jmpl %g1 + %lo(compat_sys_recvmsg), %g0 - lduwa [%o1 + 0x4] %asi, %o1 +62: lduwa [%o1 + 0x4] %asi, %o1 nop nop nop -__socketcall_table_end: do_einval: retl @@ -325,5 +325,20 @@ do_efault: .section __ex_table .align 4 - .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault + .word 1b, do_efault, 2b, do_efault, 3b, do_efault, 4b, do_efault + .word 5b, do_efault, 6b, do_efault, 7b, do_efault, 8b, do_efault + .word 9b, do_efault, 10b, do_efault, 11b, do_efault, 12b, do_efault + .word 13b, do_efault, 14b, do_efault, 15b, do_efault, 16b, do_efault + .word 17b, do_efault, 18b, do_efault, 19b, do_efault, 20b, do_efault + .word 21b, do_efault, 22b, do_efault, 23b, do_efault, 24b, do_efault + .word 25b, do_efault, 26b, do_efault, 27b, do_efault, 28b, do_efault + .word 29b, do_efault, 30b, do_efault, 31b, do_efault, 32b, do_efault + .word 33b, do_efault, 34b, do_efault, 35b, do_efault, 36b, do_efault + .word 37b, do_efault, 38b, do_efault, 39b, do_efault, 40b, do_efault + .word 41b, do_efault, 42b, do_efault, 43b, do_efault, 44b, do_efault + .word 45b, do_efault, 46b, do_efault, 47b, do_efault, 48b, do_efault + .word 49b, do_efault, 50b, do_efault, 51b, do_efault, 52b, do_efault + .word 53b, do_efault, 54b, do_efault, 55b, do_efault, 56b, do_efault + .word 57b, do_efault, 58b, do_efault, 59b, do_efault, 60b, do_efault + .word 61b, do_efault, 62b, do_efault .previous diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index f8e7005..1aa1599 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un if (regs->tstate & TSTATE_PRIV) { /* Test if this comes from uaccess places. */ - unsigned long fixup; - unsigned long g2 = regs->u_regs[UREG_G2]; + const struct exception_table_entry *entry; - if ((fixup = search_extables_range(regs->tpc, &g2))) { - /* Ouch, somebody is trying ugly VM hole tricks on us... */ + entry = search_exception_tables(regs->tpc); + if (entry) { + /* Ouch, somebody is trying VM hole tricks on us... */ #ifdef DEBUG_EXCEPTIONS printk("Exception: PC<%016lx> faddr\n", regs->tpc); - printk("EX_TABLE: insn<%016lx> fixup<%016lx> " - "g2<%016lx>\n", regs->tpc, fixup, g2); + printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n", + regs->tpc, entry->fixup); #endif - regs->tpc = fixup; + regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - regs->u_regs[UREG_G2] = g2; return; } /* Shit... */ @@ -1610,10 +1609,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned /* OK, usermode access. */ recoverable = 1; } else { - unsigned long g2 = regs->u_regs[UREG_G2]; - unsigned long fixup = search_extables_range(regs->tpc, &g2); + const struct exception_table_entry *entry; - if (fixup != 0UL) { + entry = search_exception_tables(regs->tpc); + if (entry) { /* OK, kernel access to userspace. */ recoverable = 1; @@ -1632,9 +1631,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned * recoverable condition. */ if (recoverable) { - regs->tpc = fixup; + regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - regs->u_regs[UREG_G2] = g2; } } } diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 02af08f..9d6be20 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -246,10 +246,10 @@ void kernel_mna_trap_fault(void) { struct pt_regs *regs = current_thread_info()->kern_una_regs; unsigned int insn = current_thread_info()->kern_una_insn; - unsigned long g2 = regs->u_regs[UREG_G2]; - unsigned long fixup = search_extables_range(regs->tpc, &g2); + const struct exception_table_entry *entry; - if (!fixup) { + entry = search_exception_tables(regs->tpc); + if (!entry) { unsigned long address; address = compute_effective_address(regs, insn, @@ -270,9 +270,8 @@ void kernel_mna_trap_fault(void) die_if_kernel("Oops", regs); /* Not reached */ } - regs->tpc = fixup; + regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - regs->u_regs [UREG_G2] = g2; regs->tstate &= ~TSTATE_ASI; regs->tstate |= (ASI_AIUS << 24UL); diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile index cda8733..9d0960e 100644 --- a/arch/sparc64/mm/Makefile +++ b/arch/sparc64/mm/Makefile @@ -5,6 +5,6 @@ EXTRA_AFLAGS := -ansi EXTRA_CFLAGS := -Werror -obj-y := ultra.o tlb.o fault.o init.o generic.o extable.o +obj-y := ultra.o tlb.o fault.o init.o generic.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c deleted file mode 100644 index ec33429..0000000 --- a/arch/sparc64/mm/extable.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * linux/arch/sparc64/mm/extable.c - */ - -#include -#include -#include - -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -void sort_extable(struct exception_table_entry *start, - struct exception_table_entry *finish) -{ -} - -/* Caller knows they are in a range if ret->fixup == 0 */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *start, - const struct exception_table_entry *last, - unsigned long value) -{ - const struct exception_table_entry *walk; - - /* Single insn entries are encoded as: - * word 1: insn address - * word 2: fixup code address - * - * Range entries are encoded as: - * word 1: first insn address - * word 2: 0 - * word 3: last insn address + 4 bytes - * word 4: fixup code address - * - * See asm/uaccess.h for more details. - */ - - /* 1. Try to find an exact match. */ - for (walk = start; walk <= last; walk++) { - if (walk->fixup == 0) { - /* A range entry, skip both parts. */ - walk++; - continue; - } - - if (walk->insn == value) - return walk; - } - - /* 2. Try to find a range match. */ - for (walk = start; walk <= (last - 1); walk++) { - if (walk->fixup) - continue; - - if (walk[0].insn <= value && walk[1].insn > value) - return walk; - - walk++; - } - - return NULL; -} - -/* Special extable search, which handles ranges. Returns fixup */ -unsigned long search_extables_range(unsigned long addr, unsigned long *g2) -{ - const struct exception_table_entry *entry; - - entry = search_exception_tables(addr); - if (!entry) - return 0; - - /* Inside range? Fix g2 and return correct fixup */ - if (!entry->fixup) { - *g2 = (addr - entry->insn) / 4; - return (entry + 1)->fixup; - } - - return entry->fixup; -} diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index db1e331..59dc9a2 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -242,7 +242,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn) static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, unsigned int insn, unsigned long address) { - unsigned long g2; unsigned char asi = ASI_P; if ((!insn) && (regs->tstate & TSTATE_PRIV)) @@ -273,11 +272,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, } } - g2 = regs->u_regs[UREG_G2]; - /* Is this in ex_table? */ if (regs->tstate & TSTATE_PRIV) { - unsigned long fixup; + const struct exception_table_entry *entry; if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) { if (insn & 0x2000) @@ -288,10 +285,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, /* Look in asi.h: All _S asis have LS bit set */ if ((asi & 0x1) && - (fixup = search_extables_range(regs->tpc, &g2))) { - regs->tpc = fixup; + (entry = search_exception_tables(regs->tpc))) { + regs->tpc = entry->fixup; regs->tnpc = regs->tpc + 4; - regs->u_regs[UREG_G2] = g2; return; } } else { diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h index 80a65d7..c099aa3 100644 --- a/include/asm-sparc64/uaccess.h +++ b/include/asm-sparc64/uaccess.h @@ -70,25 +70,12 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si * with the main instruction path. This means when everything is well, * we don't even have to jump over them. Further, they do not intrude * on our cache or tlb entries. - * - * There is a special way how to put a range of potentially faulting - * insns (like twenty ldd/std's with now intervening other instructions) - * You specify address of first in insn and 0 in fixup and in the next - * exception_table_entry you specify last potentially faulting insn + 1 - * and in fixup the routine which should handle the fault. - * That fixup code will get - * (faulting_insn_address - first_insn_in_the_range_address)/4 - * in %g2 (ie. index of the faulting instruction in the range). */ -struct exception_table_entry -{ - unsigned insn, fixup; +struct exception_table_entry { + unsigned int insn, fixup; }; -/* Special exable search, which handles ranges. Returns fixup */ -unsigned long search_extables_range(unsigned long addr, unsigned long *g2); - extern void __ret_efault(void); /* Uh, these should become the main single-value transfer routines.. -- cgit v0.10.2 From 5fd29752f09cabff582f65c0ce35518db4c64937 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 20:41:45 -0700 Subject: [SPARC64]: Fix fault handling in unaligned trap handler. We were not calling kernel_mna_trap_fault() correctly. Instead of being fancy, just return 0 vs. -EFAULT from the assembler stubs, and handle that return value as appropriate. Create an "__retl_efault" stub for assembler exception table entries and use it where possible. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index ecc748f..89406f9 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -540,8 +540,11 @@ bootup_user_stack_end: prom_tba: .xword 0 tlb_type: .word 0 /* Must NOT end up in BSS */ .section ".fixup",#alloc,#execinstr - .globl __ret_efault + + .globl __ret_efault, __retl_efault __ret_efault: ret restore %g0, -EFAULT, %o0 - +__retl_efault: + retl + mov -EFAULT, %o0 diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 4fb99e0..9cd272a 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -157,6 +157,9 @@ sys32_socketcall: /* %o0=call, %o1=args */ or %g2, %lo(__socketcall_table_begin), %g2 jmpl %g2 + %o0, %g0 nop +do_einval: + retl + mov -EINVAL, %o0 .align 32 __socketcall_table_begin: @@ -316,29 +319,37 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) nop nop -do_einval: - retl - mov -EINVAL, %o0 -do_efault: - retl - mov -EFAULT, %o0 - .section __ex_table .align 4 - .word 1b, do_efault, 2b, do_efault, 3b, do_efault, 4b, do_efault - .word 5b, do_efault, 6b, do_efault, 7b, do_efault, 8b, do_efault - .word 9b, do_efault, 10b, do_efault, 11b, do_efault, 12b, do_efault - .word 13b, do_efault, 14b, do_efault, 15b, do_efault, 16b, do_efault - .word 17b, do_efault, 18b, do_efault, 19b, do_efault, 20b, do_efault - .word 21b, do_efault, 22b, do_efault, 23b, do_efault, 24b, do_efault - .word 25b, do_efault, 26b, do_efault, 27b, do_efault, 28b, do_efault - .word 29b, do_efault, 30b, do_efault, 31b, do_efault, 32b, do_efault - .word 33b, do_efault, 34b, do_efault, 35b, do_efault, 36b, do_efault - .word 37b, do_efault, 38b, do_efault, 39b, do_efault, 40b, do_efault - .word 41b, do_efault, 42b, do_efault, 43b, do_efault, 44b, do_efault - .word 45b, do_efault, 46b, do_efault, 47b, do_efault, 48b, do_efault - .word 49b, do_efault, 50b, do_efault, 51b, do_efault, 52b, do_efault - .word 53b, do_efault, 54b, do_efault, 55b, do_efault, 56b, do_efault - .word 57b, do_efault, 58b, do_efault, 59b, do_efault, 60b, do_efault - .word 61b, do_efault, 62b, do_efault + .word 1b, __retl_efault, 2b, __retl_efault + .word 3b, __retl_efault, 4b, __retl_efault + .word 5b, __retl_efault, 6b, __retl_efault + .word 7b, __retl_efault, 8b, __retl_efault + .word 9b, __retl_efault, 10b, __retl_efault + .word 11b, __retl_efault, 12b, __retl_efault + .word 13b, __retl_efault, 14b, __retl_efault + .word 15b, __retl_efault, 16b, __retl_efault + .word 17b, __retl_efault, 18b, __retl_efault + .word 19b, __retl_efault, 20b, __retl_efault + .word 21b, __retl_efault, 22b, __retl_efault + .word 23b, __retl_efault, 24b, __retl_efault + .word 25b, __retl_efault, 26b, __retl_efault + .word 27b, __retl_efault, 28b, __retl_efault + .word 29b, __retl_efault, 30b, __retl_efault + .word 31b, __retl_efault, 32b, __retl_efault + .word 33b, __retl_efault, 34b, __retl_efault + .word 35b, __retl_efault, 36b, __retl_efault + .word 37b, __retl_efault, 38b, __retl_efault + .word 39b, __retl_efault, 40b, __retl_efault + .word 41b, __retl_efault, 42b, __retl_efault + .word 43b, __retl_efault, 44b, __retl_efault + .word 45b, __retl_efault, 46b, __retl_efault + .word 47b, __retl_efault, 48b, __retl_efault + .word 49b, __retl_efault, 50b, __retl_efault + .word 51b, __retl_efault, 52b, __retl_efault + .word 53b, __retl_efault, 54b, __retl_efault + .word 55b, __retl_efault, 56b, __retl_efault + .word 57b, __retl_efault, 58b, __retl_efault + .word 59b, __retl_efault, 60b, __retl_efault + .word 61b, __retl_efault, 62b, __retl_efault .previous diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S index da48400..1f5b5b7 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc64/kernel/una_asm.S @@ -6,13 +6,6 @@ .text -kernel_unaligned_trap_fault: - call kernel_mna_trap_fault - nop - retl - nop - .size kern_unaligned_trap_fault, .-kern_unaligned_trap_fault - .globl __do_int_store __do_int_store: rd %asi, %o4 @@ -51,24 +44,24 @@ __do_int_store: 0: wr %o4, 0x0, %asi retl - nop + mov 0, %o0 .size __do_int_store, .-__do_int_store .section __ex_table - .word 4b, kernel_unaligned_trap_fault - .word 5b, kernel_unaligned_trap_fault - .word 6b, kernel_unaligned_trap_fault - .word 7b, kernel_unaligned_trap_fault - .word 8b, kernel_unaligned_trap_fault - .word 9b, kernel_unaligned_trap_fault - .word 10b, kernel_unaligned_trap_fault - .word 11b, kernel_unaligned_trap_fault - .word 12b, kernel_unaligned_trap_fault - .word 13b, kernel_unaligned_trap_fault - .word 14b, kernel_unaligned_trap_fault - .word 15b, kernel_unaligned_trap_fault - .word 16b, kernel_unaligned_trap_fault - .word 17b, kernel_unaligned_trap_fault + .word 4b, __retl_efault + .word 5b, __retl_efault + .word 6b, __retl_efault + .word 7b, __retl_efault + .word 8b, __retl_efault + .word 9b, __retl_efault + .word 10b, __retl_efault + .word 11b, __retl_efault + .word 12b, __retl_efault + .word 13b, __retl_efault + .word 14b, __retl_efault + .word 15b, __retl_efault + .word 16b, __retl_efault + .word 17b, __retl_efault .previous .globl do_int_load @@ -133,21 +126,21 @@ do_int_load: 0: wr %o5, 0x0, %asi retl - nop + mov 0, %o0 .size __do_int_load, .-__do_int_load .section __ex_table - .word 4b, kernel_unaligned_trap_fault - .word 5b, kernel_unaligned_trap_fault - .word 6b, kernel_unaligned_trap_fault - .word 7b, kernel_unaligned_trap_fault - .word 8b, kernel_unaligned_trap_fault - .word 9b, kernel_unaligned_trap_fault - .word 10b, kernel_unaligned_trap_fault - .word 11b, kernel_unaligned_trap_fault - .word 12b, kernel_unaligned_trap_fault - .word 13b, kernel_unaligned_trap_fault - .word 14b, kernel_unaligned_trap_fault - .word 15b, kernel_unaligned_trap_fault - .word 16b, kernel_unaligned_trap_fault + .word 4b, __retl_efault + .word 5b, __retl_efault + .word 6b, __retl_efault + .word 7b, __retl_efault + .word 8b, __retl_efault + .word 9b, __retl_efault + .word 10b, __retl_efault + .word 11b, __retl_efault + .word 12b, __retl_efault + .word 13b, __retl_efault + .word 14b, __retl_efault + .word 15b, __retl_efault + .word 16b, __retl_efault .previous diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 9d6be20..70faf63 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -180,14 +180,14 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs) die_if_kernel(str, regs); } -extern void do_int_load(unsigned long *dest_reg, int size, - unsigned long *saddr, int is_signed, int asi); +extern int do_int_load(unsigned long *dest_reg, int size, + unsigned long *saddr, int is_signed, int asi); -extern void __do_int_store(unsigned long *dst_addr, int size, - unsigned long src_val, int asi); +extern int __do_int_store(unsigned long *dst_addr, int size, + unsigned long src_val, int asi); -static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, - struct pt_regs *regs, int asi, int orig_asi) +static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr, + struct pt_regs *regs, int asi, int orig_asi) { unsigned long zero = 0; unsigned long *src_val_p = &zero; @@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, break; }; } - __do_int_store(dst_addr, size, src_val, asi); + return __do_int_store(dst_addr, size, src_val, asi); } static inline void advance(struct pt_regs *regs) @@ -242,7 +242,7 @@ static inline int ok_for_kernel(unsigned int insn) return !floating_point_load_or_store_p(insn); } -void kernel_mna_trap_fault(void) +static void kernel_mna_trap_fault(void) { struct pt_regs *regs = current_thread_info()->kern_una_regs; unsigned int insn = current_thread_info()->kern_una_insn; @@ -294,7 +294,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u kernel_mna_trap_fault(); } else { unsigned long addr, *reg_addr; - int orig_asi, asi; + int orig_asi, asi, err; addr = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f)); @@ -319,9 +319,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u switch (dir) { case load: reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs); - do_int_load(reg_addr, size, (unsigned long *) addr, - decode_signedness(insn), asi); - if (unlikely(asi != orig_asi)) { + err = do_int_load(reg_addr, size, + (unsigned long *) addr, + decode_signedness(insn), asi); + if (likely(!err) && unlikely(asi != orig_asi)) { unsigned long val_in = *reg_addr; switch (size) { case 2: @@ -343,16 +344,19 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u break; case store: - do_int_store(((insn>>25)&0x1f), size, - (unsigned long *) addr, regs, - asi, orig_asi); + err = do_int_store(((insn>>25)&0x1f), size, + (unsigned long *) addr, regs, + asi, orig_asi); break; default: panic("Impossible kernel unaligned trap."); /* Not reached... */ } - advance(regs); + if (unlikely(err)) + kernel_mna_trap_fault(); + else + advance(regs); } } diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S index 09cbbaa..e126465 100644 --- a/arch/sparc64/lib/strncpy_from_user.S +++ b/arch/sparc64/lib/strncpy_from_user.S @@ -125,15 +125,11 @@ __strncpy_from_user: add %o2, %o3, %o0 .size __strncpy_from_user, .-__strncpy_from_user - .section .fixup,#alloc,#execinstr - .align 4 -4: retl - mov -EFAULT, %o0 - .section __ex_table,#alloc .align 4 - .word 60b, 4b - .word 61b, 4b - .word 62b, 4b - .word 63b, 4b - .word 64b, 4b + .word 60b, __retl_efault + .word 61b, __retl_efault + .word 62b, __retl_efault + .word 63b, __retl_efault + .word 64b, __retl_efault + .previous diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h index c099aa3..bc8ddbb 100644 --- a/include/asm-sparc64/uaccess.h +++ b/include/asm-sparc64/uaccess.h @@ -77,6 +77,7 @@ struct exception_table_entry { }; extern void __ret_efault(void); +extern void __retl_efault(void); /* Uh, these should become the main single-value transfer routines.. * They automatically use the right size if we just have the right -- cgit v0.10.2 From efdc1e2083e04cc70721d55803889b346c1a3de2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 21:06:47 -0700 Subject: [SPARC64]: Simplify user fault fixup handling. Instead of doing byte-at-a-time user accesses to figure out where the fault occurred, read the saved fault_address from the current thread structure. For the sake of defensive programming, if the fault_address does not fall into the user buffer range, simply assume the whole area faulted. This will cause the fixup for copy_from_user() to clear the entire kernel side buffer. Signed-off-by: David S. Miller diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c index 0278e34..19d1fdb 100644 --- a/arch/sparc64/lib/user_fixup.c +++ b/arch/sparc64/lib/user_fixup.c @@ -11,61 +11,56 @@ /* Calculating the exact fault address when using * block loads and stores can be very complicated. + * * Instead of trying to be clever and handling all * of the cases, just fix things up simply here. */ -unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) +static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset) { - char *dst = to; - const char __user *src = from; + unsigned long fault_addr = current_thread_info()->fault_address; + unsigned long end = start + size; - while (size) { - if (__get_user(*dst, src)) - break; - dst++; - src++; - size--; + if (fault_addr < start || fault_addr >= end) { + *offset = 0; + } else { + *offset = start - fault_addr; + size = end - fault_addr; } + return size; +} - if (size) - memset(dst, 0, size); +unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size) +{ + unsigned long offset; + + size = compute_size((unsigned long) from, size, &offset); + if (likely(size)) + memset(to + offset, 0, size); return size; } unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size) { - char __user *dst = to; - const char *src = from; - - while (size) { - if (__put_user(*src, dst)) - break; - dst++; - src++; - size--; - } + unsigned long offset; - return size; + return compute_size((unsigned long) to, size, &offset); } unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size) { - char __user *dst = to; - char __user *src = from; + unsigned long fault_addr = current_thread_info()->fault_address; + unsigned long start = (unsigned long) to; + unsigned long end = start + size; - while (size) { - char tmp; + if (fault_addr >= start && fault_addr < end) + return end - fault_addr; - if (__get_user(tmp, src)) - break; - if (__put_user(tmp, dst)) - break; - dst++; - src++; - size--; - } + start = (unsigned long) from; + end = start + size; + if (fault_addr >= start && fault_addr < end) + return end - fault_addr; return size; } diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 59dc9a2..4a52e79 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -457,7 +457,7 @@ good_area: } up_read(&mm->mmap_sem); - goto fault_done; + return; /* * Something tried to access memory that isn't in our memory map.. @@ -469,8 +469,7 @@ bad_area: handle_kernel_fault: do_kernel_fault(regs, si_code, fault_code, insn, address); - - goto fault_done; + return; /* * We ran out of memory, or some other thing happened to us that made @@ -501,9 +500,4 @@ do_sigbus: /* Kernel mode? Handle exceptions or die */ if (regs->tstate & TSTATE_PRIV) goto handle_kernel_fault; - -fault_done: - /* These values are no longer needed, clear them. */ - set_thread_fault_code(0); - current_thread_info()->fault_address = 0; } diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h index bc8ddbb..203e8ee 100644 --- a/include/asm-sparc64/uaccess.h +++ b/include/asm-sparc64/uaccess.h @@ -251,7 +251,7 @@ copy_from_user(void *to, const void __user *from, unsigned long size) { unsigned long ret = ___copy_from_user(to, from, size); - if (ret) + if (unlikely(ret)) ret = copy_from_user_fixup(to, from, size); return ret; } @@ -267,7 +267,7 @@ copy_to_user(void __user *to, const void *from, unsigned long size) { unsigned long ret = ___copy_to_user(to, from, size); - if (ret) + if (unlikely(ret)) ret = copy_to_user_fixup(to, from, size); return ret; } @@ -283,7 +283,7 @@ copy_in_user(void __user *to, void __user *from, unsigned long size) { unsigned long ret = ___copy_in_user(to, from, size); - if (ret) + if (unlikely(ret)) ret = copy_in_user_fixup(to, from, size); return ret; } -- cgit v0.10.2 From 801ab3c731e77324c055769491711e620100dbfb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 21:31:25 -0700 Subject: [SPARC]: Declare paging_init() in asm/pgtable.h Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 53c192a..3509e43 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -249,8 +249,6 @@ struct tt_entry *sparc_ttable; struct pt_regs fake_swapper_regs; -extern void paging_init(void); - void __init setup_arch(char **cmdline_p) { int i; diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 8e8baf2..516f485 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -492,8 +492,6 @@ void register_prom_callbacks(void) "' linux-.soft2 to .soft2"); } -extern void paging_init(void); - void __init setup_arch(char **cmdline_p) { int i; diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index 8f4f6a9..8395ad2 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -82,6 +82,8 @@ extern unsigned long page_kernel; /* Top-level page directory */ extern pgd_t swapper_pg_dir[1024]; +extern void paging_init(void); + /* Page table for 0-4MB for everybody, on the Sparc this * holds the same as on the i386. */ diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 53d612a..82273c8 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -341,6 +341,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p extern pgd_t swapper_pg_dir[2048]; extern pmd_t swapper_low_pmd_dir[2048]; +extern void paging_init(void); + /* These do nothing with the way I have things setup. */ #define mmu_lockarea(vaddr, len) (vaddr) #define mmu_unlockarea(vaddr, len) do { } while(0) -- cgit v0.10.2 From 0836a0eb4073c3e0a09c5965833b9dec19f5abc7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 21:38:08 -0700 Subject: [SPARC64]: Move phys_base, kern_{base,size}, and sp_banks[] init to paging_init Also, move prom_probe_memory() into arch/sparc64/mm/init.c Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 516f485..4c9c8f2 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -464,8 +464,6 @@ static void __init boot_flags_init(char *commands) } } -extern int prom_probe_memory(void); -extern unsigned long start, end; extern void panic_setup(char *, int *); extern unsigned short root_flags; @@ -494,8 +492,6 @@ void register_prom_callbacks(void) void __init setup_arch(char **cmdline_p) { - int i; - /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); strcpy(saved_command_line, *cmdline_p); @@ -514,21 +510,6 @@ void __init setup_arch(char **cmdline_p) boot_flags_init(*cmdline_p); idprom_init(); - (void) prom_probe_memory(); - - phys_base = 0xffffffffffffffffUL; - for (i = 0; sp_banks[i].num_bytes != 0; i++) { - unsigned long top; - - if (sp_banks[i].base_addr < phys_base) - phys_base = sp_banks[i].base_addr; - top = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - } - pfn_base = phys_base >> PAGE_SHIFT; - - kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; - kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; if (!root_flags) root_mountflags &= ~MS_RDONLY; diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 4a52e79..80793d6 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -71,53 +71,6 @@ void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) : "memory"); } -/* Nice, simple, prom library does all the sweating for us. ;) */ -unsigned long __init prom_probe_memory (void) -{ - register struct linux_mlist_p1275 *mlist; - register unsigned long bytes, base_paddr, tally; - register int i; - - i = 0; - mlist = *prom_meminfo()->p1275_available; - bytes = tally = mlist->num_bytes; - base_paddr = mlist->start_adr; - - sp_banks[0].base_addr = base_paddr; - sp_banks[0].num_bytes = bytes; - - while (mlist->theres_more != (void *) 0) { - i++; - mlist = mlist->theres_more; - bytes = mlist->num_bytes; - tally += bytes; - if (i >= SPARC_PHYS_BANKS-1) { - printk ("The machine has more banks than " - "this kernel can support\n" - "Increase the SPARC_PHYS_BANKS " - "setting (currently %d)\n", - SPARC_PHYS_BANKS); - i = SPARC_PHYS_BANKS-1; - break; - } - - sp_banks[i].base_addr = mlist->start_adr; - sp_banks[i].num_bytes = mlist->num_bytes; - } - - i++; - sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; - sp_banks[i].num_bytes = 0; - - /* Now mask all bank sizes on a page boundary, it is all we can - * use anyways. - */ - for (i = 0; sp_banks[i].num_bytes != 0; i++) - sp_banks[i].num_bytes &= PAGE_MASK; - - return tally; -} - static void __kprobes unhandled_fault(unsigned long address, struct task_struct *tsk, struct pt_regs *regs) diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 9f6ca62..63a7b9b 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1425,6 +1425,50 @@ void kernel_map_pages(struct page *page, int numpages, int enable) } #endif +static void __init prom_probe_memory(void) +{ + struct linux_mlist_p1275 *mlist; + unsigned long bytes, base_paddr, tally; + int i; + + i = 0; + mlist = *prom_meminfo()->p1275_available; + bytes = tally = mlist->num_bytes; + base_paddr = mlist->start_adr; + + sp_banks[0].base_addr = base_paddr; + sp_banks[0].num_bytes = bytes; + + while (mlist->theres_more != (void *) 0) { + i++; + mlist = mlist->theres_more; + bytes = mlist->num_bytes; + tally += bytes; + if (i >= SPARC_PHYS_BANKS-1) { + printk ("The machine has more banks than " + "this kernel can support\n" + "Increase the SPARC_PHYS_BANKS " + "setting (currently %d)\n", + SPARC_PHYS_BANKS); + i = SPARC_PHYS_BANKS-1; + break; + } + + sp_banks[i].base_addr = mlist->start_adr; + sp_banks[i].num_bytes = mlist->num_bytes; + } + + i++; + sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; + sp_banks[i].num_bytes = 0; + + /* Now mask all bank sizes on a page boundary, it is all we can + * use anyways. + */ + for (i = 0; sp_banks[i].num_bytes != 0; i++) + sp_banks[i].num_bytes &= PAGE_MASK; +} + /* paging_init() sets up the page tables */ extern void cheetah_ecache_flush_init(void); @@ -1435,7 +1479,23 @@ pgd_t swapper_pg_dir[2048]; void __init paging_init(void) { unsigned long end_pfn, pages_avail, shift; - unsigned long real_end; + unsigned long real_end, i; + + prom_probe_memory(); + + phys_base = 0xffffffffffffffffUL; + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long top; + + if (sp_banks[i].base_addr < phys_base) + phys_base = sp_banks[i].base_addr; + top = sp_banks[i].base_addr + + sp_banks[i].num_bytes; + } + pfn_base = phys_base >> PAGE_SHIFT; + + kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; set_bit(0, mmu_context_bmap); -- cgit v0.10.2 From 10147570f9eaff3920f0c67bad7244c2eb958d4f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 21:46:43 -0700 Subject: [SPARC64]: Kill all external references to sp_banks[] Thus, we can mark sp_banks[] static in arch/sparc64/mm/init.c Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 1aa1599..eeb1e83 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -757,26 +757,12 @@ void __init cheetah_ecache_flush_init(void) ecache_flush_size = (2 * largest_size); ecache_flush_linesize = smallest_linesize; - /* Discover a physically contiguous chunk of physical - * memory in 'sp_banks' of size ecache_flush_size calculated - * above. Store the physical base of this area at - * ecache_flush_physbase. - */ - for (node = 0; ; node++) { - if (sp_banks[node].num_bytes == 0) - break; - if (sp_banks[node].num_bytes >= ecache_flush_size) { - ecache_flush_physbase = sp_banks[node].base_addr; - break; - } - } + ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size); - /* Note: Zero would be a valid value of ecache_flush_physbase so - * don't use that as the success test. :-) - */ - if (sp_banks[node].num_bytes == 0) { + if (ecache_flush_physbase == ~0UL) { prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " - "contiguous physical memory.\n", ecache_flush_size); + "contiguous physical memory.\n", + ecache_flush_size); prom_halt(); } @@ -1345,16 +1331,9 @@ static int cheetah_fix_ce(unsigned long physaddr) /* Return non-zero if PADDR is a valid physical memory address. */ static int cheetah_check_main_memory(unsigned long paddr) { - int i; + unsigned long vaddr = PAGE_OFFSET + paddr; - for (i = 0; ; i++) { - if (sp_banks[i].num_bytes == 0) - break; - if (paddr >= sp_banks[i].base_addr && - paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes)) - return 1; - } - return 0; + return kern_addr_valid(vaddr); } void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar) diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 80793d6..31fbc67 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -32,8 +32,6 @@ #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) -extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; - /* * To debug kernel to catch accesses to certain virtual/physical addresses. * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 63a7b9b..48851a2 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -41,7 +41,14 @@ extern void device_scan(void); -struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; +struct sparc_phys_banks { + unsigned long base_addr; + unsigned long num_bytes; +}; + +#define SPARC_PHYS_BANKS 32 + +static struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; unsigned long *sparc64_valid_addr_bitmap __read_mostly; @@ -1425,6 +1432,20 @@ void kernel_map_pages(struct page *page, int numpages, int enable) } #endif +unsigned long __init find_ecache_flush_span(unsigned long size) +{ + unsigned long i; + + for (i = 0; ; i++) { + if (sp_banks[i].num_bytes == 0) + break; + if (sp_banks[i].num_bytes >= size) + return sp_banks[i].base_addr; + } + + return ~0UL; +} + static void __init prom_probe_memory(void) { struct linux_mlist_p1275 *mlist; diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index 7f8d764..5426bb2 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h @@ -140,23 +140,6 @@ extern unsigned long page_to_pfn(struct page *); #define virt_to_phys __pa #define phys_to_virt __va -/* The following structure is used to hold the physical - * memory configuration of the machine. This is filled in - * probe_memory() and is later used by mem_init() to set up - * mem_map[]. We statically allocate SPARC_PHYS_BANKS of - * these structs, this is arbitrary. The entry after the - * last valid one has num_bytes==0. - */ - -struct sparc_phys_banks { - unsigned long base_addr; - unsigned long num_bytes; -}; - -#define SPARC_PHYS_BANKS 32 - -extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; - #endif /* !(__ASSEMBLY__) */ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 82273c8..8c6dfc6c 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -342,6 +342,7 @@ extern pgd_t swapper_pg_dir[2048]; extern pmd_t swapper_low_pmd_dir[2048]; extern void paging_init(void); +extern unsigned long find_ecache_flush_span(unsigned long size); /* These do nothing with the way I have things setup. */ #define mmu_lockarea(vaddr, len) (vaddr) -- cgit v0.10.2 From ed3ffaf7b5e0262cb860f106a6632933671cc88f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 21:48:25 -0700 Subject: [SPARC64]: Solidify check in cheetah_check_main_memory(). Need to make sure the address is below high_memory before passing it to kern_addr_valid(). Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index eeb1e83..7f190fc 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1333,6 +1333,9 @@ static int cheetah_check_main_memory(unsigned long paddr) { unsigned long vaddr = PAGE_OFFSET + paddr; + if (vaddr > high_memory) + return 0; + return kern_addr_valid(vaddr); } -- cgit v0.10.2 From 01d40f28b125e0a9aa0ec24642be67fc4c5dfaff Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 28 Sep 2005 22:37:53 -0700 Subject: [NET]: Fix reversed logic in eth_type_trans(). I got the second compare_eth_addr() test reversed, oops. Signed-off-by: David S. Miller diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 8b299cc..68a5ca8 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -191,7 +191,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) */ else if(1 /*dev->flags&IFF_PROMISC*/) { - if (unlikely(!compare_eth_addr(eth->h_dest, dev->dev_addr))) + if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr))) skb->pkt_type = PACKET_OTHERHOST; } -- cgit v0.10.2 From ca5da7106214e03f5302ca630bd38a9145b27391 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Sep 2005 09:44:54 +0100 Subject: [ARM] pxafb: Remove #if DEBUG, convert DPRINTK to pr_debug Fix warning: drivers/video/pxafb.h:119:5: warning: "DEBUG" is not defined by removing the whole #if DEBUG #define DPRINTK(fmt, args...) printk...etc... #else #define DPRINTK(fmt, args...) #endif stuff - we have pr_debug() for this. Signed-off-by: Russell King diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 34d4dcc..194eed0 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -260,9 +260,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) } #ifdef CONFIG_CPU_FREQ - DPRINTK("dma period = %d ps, clock = %d kHz\n", - pxafb_display_dma_period(var), - get_clk_frequency_khz(0)); + pr_debug("pxafb: dma period = %d ps, clock = %d kHz\n", + pxafb_display_dma_period(var), + get_clk_frequency_khz(0)); #endif return 0; @@ -270,7 +270,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static inline void pxafb_set_truecolor(u_int is_true_color) { - DPRINTK("true_color = %d\n", is_true_color); + pr_debug("pxafb: true_color = %d\n", is_true_color); // do your machine-specific setup if needed } @@ -284,7 +284,7 @@ static int pxafb_set_par(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; unsigned long palette_mem_size; - DPRINTK("set_par\n"); + pr_debug("pxafb: set_par\n"); if (var->bits_per_pixel == 16) fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; @@ -308,7 +308,7 @@ static int pxafb_set_par(struct fb_info *info) palette_mem_size = fbi->palette_size * sizeof(u16); - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); + pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; @@ -369,7 +369,7 @@ static int pxafb_blank(int blank, struct fb_info *info) struct pxafb_info *fbi = (struct pxafb_info *)info; int i; - DPRINTK("pxafb_blank: blank=%d\n", blank); + pr_debug("pxafb: blank=%d\n", blank); switch (blank) { case FB_BLANK_POWERDOWN: @@ -508,15 +508,15 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * u_long flags; u_int lines_per_panel, pcd = get_pcd(var->pixclock); - DPRINTK("Configuring PXA LCD\n"); + pr_debug("pxafb: Configuring PXA LCD\n"); - DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", - var->xres, var->hsync_len, - var->left_margin, var->right_margin); - DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", - var->yres, var->vsync_len, - var->upper_margin, var->lower_margin); - DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd); + pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n", + var->xres, var->hsync_len, + var->left_margin, var->right_margin); + pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n", + var->yres, var->vsync_len, + var->upper_margin, var->lower_margin); + pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd); #if DEBUG_VAR if (var->xres < 16 || var->xres > 1024) @@ -589,10 +589,10 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * if (pcd) new_regs.lccr3 |= LCCR3_PixClkDiv(pcd); - DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0); - DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1); - DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2); - DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3); + pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0); + pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1); + pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2); + pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3); /* Update shadow copy atomically */ local_irq_save(flags); @@ -637,24 +637,24 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * } #if 0 - DPRINTK("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu); - DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu); - DPRINTK("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu); - DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma); - DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma); - DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma); - - DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr); - DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr); - DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr); - DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr); - - DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd); - DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd); - DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd); + pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu); + pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu); + pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu); + pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma); + pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma); + pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma); + + pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr); + pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr); + pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr); + + pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr); + pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr); + pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr); + + pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd); + pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd); + pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd); #endif fbi->reg_lccr0 = new_regs.lccr0; @@ -684,7 +684,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info * */ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) { - DPRINTK("backlight o%s\n", on ? "n" : "ff"); + pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff"); if (pxafb_backlight_power) pxafb_backlight_power(on); @@ -692,7 +692,7 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on) static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on) { - DPRINTK("LCD power o%s\n", on ? "n" : "ff"); + pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff"); if (pxafb_lcd_power) pxafb_lcd_power(on); @@ -740,13 +740,13 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi) static void pxafb_enable_controller(struct pxafb_info *fbi) { - DPRINTK("Enabling LCD controller\n"); - DPRINTK("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); - DPRINTK("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); - DPRINTK("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0); - DPRINTK("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1); - DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); - DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); + pr_debug("pxafb: Enabling LCD controller\n"); + pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0); + pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1); + pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0); + pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1); + pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2); + pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3); /* enable LCD controller clock */ pxa_set_cken(CKEN16_LCD, 1); @@ -761,19 +761,19 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) FDADR1 = fbi->fdadr1; LCCR0 |= LCCR0_ENB; - DPRINTK("FDADR0 0x%08x\n", (unsigned int) FDADR0); - DPRINTK("FDADR1 0x%08x\n", (unsigned int) FDADR1); - DPRINTK("LCCR0 0x%08x\n", (unsigned int) LCCR0); - DPRINTK("LCCR1 0x%08x\n", (unsigned int) LCCR1); - DPRINTK("LCCR2 0x%08x\n", (unsigned int) LCCR2); - DPRINTK("LCCR3 0x%08x\n", (unsigned int) LCCR3); + pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0); + pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1); + pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0); + pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1); + pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2); + pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3); } static void pxafb_disable_controller(struct pxafb_info *fbi) { DECLARE_WAITQUEUE(wait, current); - DPRINTK("Disabling LCD controller\n"); + pr_debug("pxafb: disabling LCD controller\n"); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&fbi->ctrlr_wait, &wait); @@ -1039,7 +1039,7 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi) fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16; palette_mem_size = fbi->palette_size * sizeof(u16); - DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); + pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 22c00be..47f41f7 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -114,15 +114,6 @@ struct pxafb_info { #define PXA_NAME "PXA" /* - * Debug macros - */ -#if DEBUG -# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) -#else -# define DPRINTK(fmt, args...) -#endif - -/* * Minimum X and Y resolutions */ #define MIN_XRES 64 -- cgit v0.10.2 From eb9181a2f85d46cdbbd3cb18b4541f8ab2df0933 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Sep 2005 09:49:25 +0100 Subject: [ARM] Fix warning in arch/arm/mach-pxa/generic.c Fix arch/arm/mach-pxa/generic.c:242: warning: 'struct i2c_pxa_platform_data' declared inside parameter list caused by missing asm/arch/i2c.h include. Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index a45aaa1..d0660a8 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "generic.h" -- cgit v0.10.2 From d0877904470c149c6553f1309cfed6c90d67cf91 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Sep 2005 11:12:52 +0100 Subject: [ARM] Don't include asm/arch/hardware.h directly Since asm/hardware.h's only reason for existing is to include asm/arch/hardware.h, it's completely pointless to include both. Signed-off-by: Russell King diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index 2a7fee2..5fd8c9f 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -12,7 +12,6 @@ #include #include -#include /* * IRQ base register diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 817620d..198c1c6 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -18,7 +18,6 @@ #include #include -#include extern int usb_disabled(void); diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 5cde76f..d8f3ba7 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include -- cgit v0.10.2 From fc611a1a50caa04bae82ed3c1fc6505132f8343f Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 29 Sep 2005 11:15:51 +0100 Subject: [ARM] Don't include mach-types.h unnecessarily It's pointless to include mach-types.h if you're not going to use anything from it. These references were removed as a result of: grep -lr 'asm/mach-types\.h' . | xargs grep -L 'machine_is_\|MACH_TYPE_\|MACHINE_START\|machine_type' Signed-off-by: Russell King diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index a7bd857..e8053d1 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-imx/leds-mx1ads.c b/arch/arm/mach-imx/leds-mx1ads.c index e6399b0..7923640 100644 --- a/arch/arm/mach-imx/leds-mx1ads.c +++ b/arch/arm/mach-imx/leds-mx1ads.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "leds.h" /* diff --git a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c index bda7394..fdeeef4 100644 --- a/arch/arm/mach-iop3xx/common.c +++ b/arch/arm/mach-iop3xx/common.c @@ -27,7 +27,6 @@ unsigned long iop3xx_pcibios_min_mem = 0; /* * Default power-off for EP80219 */ -#include static inline void ep80219_send_to_pic(__u8 c) { } diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c index 0039793..d67ac0e 100644 --- a/arch/arm/mach-iop3xx/iop321-time.c +++ b/arch/arm/mach-iop3xx/iop321-time.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c index 8eddfac..3c1f0eb 100644 --- a/arch/arm/mach-iop3xx/iop331-time.c +++ b/arch/arm/mach-iop3xx/iop331-time.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c index b01042f..55992ab 100644 --- a/arch/arm/mach-iop3xx/iq31244-mm.c +++ b/arch/arm/mach-iop3xx/iq31244-mm.c @@ -21,7 +21,6 @@ #include #include -#include /* diff --git a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c index 1580c7e..bb3e9e5 100644 --- a/arch/arm/mach-iop3xx/iq80321-mm.c +++ b/arch/arm/mach-iop3xx/iq80321-mm.c @@ -21,7 +21,6 @@ #include #include -#include /* diff --git a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c index ee8c333..129eb49 100644 --- a/arch/arm/mach-iop3xx/iq80331-mm.c +++ b/arch/arm/mach-iop3xx/iq80331-mm.c @@ -21,7 +21,6 @@ #include #include -#include /* diff --git a/arch/arm/mach-iop3xx/iq80332-mm.c b/arch/arm/mach-iop3xx/iq80332-mm.c index 084afcd..2feaf75 100644 --- a/arch/arm/mach-iop3xx/iq80332-mm.c +++ b/arch/arm/mach-iop3xx/iq80332-mm.c @@ -21,7 +21,6 @@ #include #include -#include /* diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 74bd2fd..f34797a 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c index 0788fb2..522205a 100644 --- a/arch/arm/mach-ixp2000/pci.c +++ b/arch/arm/mach-ixp2000/pci.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c index c5efcd0..c02ef7c 100644 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ b/arch/arm/mach-pxa/corgi_lcd.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index f021fd8..5098b50 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "devs.h" #include "usb-simtec.h" diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 3c8862f..6a291e6 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c index d1565e8..b80d57d 100644 --- a/arch/arm/mach-versatile/pci.c +++ b/arch/arm/mach-versatile/pci.c @@ -29,7 +29,6 @@ #include #include #include -#include /* * these spaces are mapped using the following base registers: diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 6cb20ae..02bcc6c 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index 409aac2..fd894bb 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 98f1c76..14a836d 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index 0c45464..0ba0ff7 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c @@ -39,7 +39,6 @@ #include #include -#include #include #include diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index 3e94b61..a9f86c7 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -30,7 +30,6 @@ #include #include -#include #include #include diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 5afe660..05f4842 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index 8cc7140..b17bca6 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c @@ -42,7 +42,6 @@ #include #include -#include #include #include diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 5238570..8dcaa35 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 891e3a1..b47ebcb 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -58,7 +58,6 @@ #include #include -#include #include #include diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index 08d1c92..94be9e5 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index c361c6f..3c04f59 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -82,8 +82,6 @@ #include #include -#include - /* structures */ struct s3c24xx_uart_info { diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 198c1c6..859aca7b 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -17,7 +17,6 @@ */ #include -#include extern int usb_disabled(void); diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 3d9bcf7..da7d547 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -20,7 +20,6 @@ */ #include -#include #include #include diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 630f2df..3c72c62 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -19,7 +19,6 @@ #include #include -#include #include #define CORGI_DEFAULT_INTENSITY 0x1f diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 6c2244c..1d54d3d6 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -36,7 +36,6 @@ #include #include -#include #include #include -- cgit v0.10.2 From a0800f6da7c4590d49ae513d9d5ee8b1ad203b82 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 29 Sep 2005 16:21:50 +0200 Subject: [WATCHDOG] pcwd_pci.c control status + boot-code clean-up * Clean-up control status code (use control status defines + change pcipcwd_clear_status) * Clean-up boot-code (move card info to pcipcwd_show_card_info() ) Signed-off-by: Wim Van Sebroeck diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 5a80adb..0cb62e3 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c @@ -50,8 +50,8 @@ #include /* For inb/outb/... */ /* Module and version information */ -#define WATCHDOG_VERSION "1.01" -#define WATCHDOG_DATE "02 Sep 2005" +#define WATCHDOG_VERSION "1.02" +#define WATCHDOG_DATE "03 Sep 2005" #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" #define WATCHDOG_NAME "pcwd_pci" #define PFX WATCHDOG_NAME ": " @@ -70,19 +70,30 @@ * These are the defines that describe the control status bits for the * PCI-PC Watchdog card. */ -#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ -#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ -#define WD_PCI_TTRP 0x04 /* Temperature Trip status */ +/* Port 1 : Control Status #1 */ +#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ +#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ +#define WD_PCI_TTRP 0x04 /* Temperature Trip status */ +#define WD_PCI_RL2A 0x08 /* Relay 2 Active */ +#define WD_PCI_RL1A 0x10 /* Relay 1 Active */ +#define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip/reset */ +#define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */ +/* Port 2 : Control Status #2 */ +#define WD_PCI_WDIS 0x10 /* Watchdog Disable */ +#define WD_PCI_ENTP 0x20 /* Enable Temperature Trip Reset */ +#define WD_PCI_WRSP 0x40 /* Watchdog wrote response */ +#define WD_PCI_PCMD 0x80 /* PC has sent command */ /* according to documentation max. time to process a command for the pci * watchdog card is 100 ms, so we give it 150 ms to do it's job */ #define PCI_COMMAND_TIMEOUT 150 /* Watchdog's internal commands */ -#define CMD_GET_STATUS 0x04 -#define CMD_GET_FIRMWARE_VERSION 0x08 -#define CMD_READ_WATCHDOG_TIMEOUT 0x18 -#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 +#define CMD_GET_STATUS 0x04 +#define CMD_GET_FIRMWARE_VERSION 0x08 +#define CMD_READ_WATCHDOG_TIMEOUT 0x18 +#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 +#define CMD_GET_CLEAR_RESET_COUNT 0x84 /* We can only use 1 card due to the /dev/watchdog restriction */ static int cards_found; @@ -91,12 +102,12 @@ static int cards_found; static int temp_panic; static unsigned long is_active; static char expect_release; -static struct { - int supports_temp; /* Wether or not the card has a temperature device */ - int boot_status; /* The card's boot status */ - unsigned long io_addr; /* The cards I/O address */ - spinlock_t io_lock; - struct pci_dev *pdev; +static struct { /* this is private data for each PCI-PC watchdog card */ + int supports_temp; /* Wether or not the card has a temperature device */ + int boot_status; /* The card's boot status */ + unsigned long io_addr; /* The cards I/O address */ + spinlock_t io_lock; /* the lock for io operations */ + struct pci_dev *pdev; /* the PCI-device */ } pcipcwd_private; /* module parameters */ @@ -131,10 +142,10 @@ static int send_command(int cmd, int *msb, int *lsb) /* wait till the pci card processed the command, signaled by * the WRSP bit in port 2 and give it a max. timeout of * PCI_COMMAND_TIMEOUT to process */ - got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; + got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { mdelay(1); - got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; + got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; } if (got_response) { @@ -150,6 +161,55 @@ static int send_command(int cmd, int *msb, int *lsb) return got_response; } +static inline void pcipcwd_check_temperature_support(void) +{ + if (inb_p(pcipcwd_private.io_addr) != 0xF0) + pcipcwd_private.supports_temp = 1; +} + +static int pcipcwd_get_option_switches(void) +{ + int option_switches; + + option_switches = inb_p(pcipcwd_private.io_addr + 3); + return option_switches; +} + +static void pcipcwd_show_card_info(void) +{ + int got_fw_rev, fw_rev_major, fw_rev_minor; + char fw_ver_str[20]; /* The cards firmware version */ + int option_switches; + + got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + if (got_fw_rev) { + sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); + } else { + sprintf(fw_ver_str, ""); + } + + /* Get switch settings */ + option_switches = pcipcwd_get_option_switches(); + + printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", + (int) pcipcwd_private.io_addr, fw_ver_str, + (pcipcwd_private.supports_temp ? "with" : "without")); + + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + if (pcipcwd_private.boot_status & WDIOF_CARDRESET) + printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); + + if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) + printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); + + if (pcipcwd_private.boot_status == 0) + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); +} + static int pcipcwd_start(void) { int stat_reg; @@ -161,7 +221,7 @@ static int pcipcwd_start(void) stat_reg = inb_p(pcipcwd_private.io_addr + 2); spin_unlock(&pcipcwd_private.io_lock); - if (stat_reg & 0x10) { + if (stat_reg & WD_PCI_WDIS) { printk(KERN_ERR PFX "Card timer not enabled\n"); return -1; } @@ -183,7 +243,7 @@ static int pcipcwd_stop(void) stat_reg = inb_p(pcipcwd_private.io_addr + 2); spin_unlock(&pcipcwd_private.io_lock); - if (!(stat_reg & 0x10)) { + if (!(stat_reg & WD_PCI_WDIS)) { printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); return -1; } @@ -194,7 +254,7 @@ static int pcipcwd_stop(void) static int pcipcwd_keepalive(void) { /* Re-trigger watchdog by writing to port 0 */ - outb_p(0x42, pcipcwd_private.io_addr); + outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */ return 0; } @@ -215,13 +275,13 @@ static int pcipcwd_set_heartbeat(int t) static int pcipcwd_get_status(int *status) { - int new_status; + int control_status; *status=0; - new_status = inb_p(pcipcwd_private.io_addr + 1); - if (new_status & WD_PCI_WTRP) + control_status = inb_p(pcipcwd_private.io_addr + 1); + if (control_status & WD_PCI_WTRP) *status |= WDIOF_CARDRESET; - if (new_status & WD_PCI_TTRP) { + if (control_status & WD_PCI_TTRP) { *status |= WDIOF_OVERHEAT; if (temp_panic) panic(PFX "Temperature overheat trip!\n"); @@ -232,7 +292,20 @@ static int pcipcwd_get_status(int *status) static int pcipcwd_clear_status(void) { - outb_p(0x01, pcipcwd_private.io_addr + 1); + int control_status; + int msb; + int reset_counter; + + control_status = inb_p(pcipcwd_private.io_addr + 1); + + /* clear trip status & LED and keep mode of relay 2 */ + outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); + + /* clear reset counter */ + msb=0; + reset_counter=0xff; + send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); + return 0; } @@ -242,11 +315,13 @@ static int pcipcwd_get_temperature(int *temperature) if (!pcipcwd_private.supports_temp) return -ENODEV; + *temperature = inb_p(pcipcwd_private.io_addr); + /* * Convert celsius to fahrenheit, since this was * the decided 'standard' for this return value. */ - *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; + *temperature = (*temperature * 9 / 5) + 32; return 0; } @@ -256,7 +331,7 @@ static int pcipcwd_get_temperature(int *temperature) */ static ssize_t pcipcwd_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) + size_t len, loff_t *ppos) { /* See if we got the magic character 'V' and reload the timer */ if (len) { @@ -381,8 +456,9 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, static int pcipcwd_open(struct inode *inode, struct file *file) { /* /dev/watchdog can only be opened once */ - if (test_and_set_bit(0, &is_active)) + if (test_and_set_bit(0, &is_active)) { return -EBUSY; + } /* Activate */ pcipcwd_start(); @@ -492,19 +568,10 @@ static struct notifier_block pcipcwd_notifier = { * Init & exit routines */ -static inline void check_temperature_support(void) -{ - if (inb_p(pcipcwd_private.io_addr) != 0xF0) - pcipcwd_private.supports_temp = 1; -} - static int __devinit pcipcwd_card_init(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret = -EIO; - int got_fw_rev, fw_rev_major, fw_rev_minor; - char fw_ver_str[20]; - char option_switches; cards_found++; if (cards_found == 1) @@ -546,36 +613,10 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev, pcipcwd_stop(); /* Check whether or not the card supports the temperature device */ - check_temperature_support(); - - /* Get the Firmware Version */ - got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); - if (got_fw_rev) { - sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); - } else { - sprintf(fw_ver_str, ""); - } + pcipcwd_check_temperature_support(); - /* Get switch settings */ - option_switches = inb_p(pcipcwd_private.io_addr + 3); - - printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", - (int) pcipcwd_private.io_addr, fw_ver_str, - (pcipcwd_private.supports_temp ? "with" : "without")); - - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", - option_switches, - ((option_switches & 0x10) ? "ON" : "OFF"), - ((option_switches & 0x08) ? "ON" : "OFF")); - - if (pcipcwd_private.boot_status & WDIOF_CARDRESET) - printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); - - if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) - printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); - - if (pcipcwd_private.boot_status == 0) - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + /* Show info about the card itself */ + pcipcwd_show_card_info(); /* Check that the heartbeat value is within it's range ; if not reset to the default */ if (pcipcwd_set_heartbeat(heartbeat)) { @@ -656,7 +697,7 @@ static struct pci_driver pcipcwd_driver = { static int __init pcipcwd_init_module(void) { - spin_lock_init (&pcipcwd_private.io_lock); + spin_lock_init(&pcipcwd_private.io_lock); return pci_register_driver(&pcipcwd_driver); } -- cgit v0.10.2 From 195331d7c9813fe7f1a93c09afa2c7dcdf2790a8 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Thu, 29 Sep 2005 16:22:30 +0200 Subject: [WATCHDOG] pcwd_pci.c add debug module_param Add debugging code for the pcwd_pci driver. Signed-off-by: Wim Van Sebroeck diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 0cb62e3..0b8e493 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c @@ -111,6 +111,13 @@ static struct { /* this is private data for each PCI-PC watchdog card */ } pcipcwd_private; /* module parameters */ +#define QUIET 0 /* Default */ +#define VERBOSE 1 /* Verbose */ +#define DEBUG 2 /* print fancy stuff too */ +static int debug = QUIET; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); + #define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ static int heartbeat = WATCHDOG_HEARTBEAT; module_param(heartbeat, int, 0); @@ -128,6 +135,10 @@ static int send_command(int cmd, int *msb, int *lsb) { int got_response, count; + if (debug >= DEBUG) + printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n", + cmd, *msb, *lsb); + spin_lock(&pcipcwd_private.io_lock); /* If a command requires data it should be written first. * Data for commands with 8 bits of data should be written to port 4. @@ -148,6 +159,15 @@ static int send_command(int cmd, int *msb, int *lsb) got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; } + if (debug >= DEBUG) { + if (got_response) { + printk(KERN_DEBUG PFX "time to process command was: %d ms\n", + count); + } else { + printk(KERN_DEBUG PFX "card did not respond on command!\n"); + } + } + if (got_response) { /* read back response */ *lsb = inb_p(pcipcwd_private.io_addr + 4); @@ -155,7 +175,12 @@ static int send_command(int cmd, int *msb, int *lsb) /* clear WRSP bit */ inb_p(pcipcwd_private.io_addr + 6); + + if (debug >= DEBUG) + printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", + cmd, *msb, *lsb); } + spin_unlock(&pcipcwd_private.io_lock); return got_response; @@ -226,6 +251,9 @@ static int pcipcwd_start(void) return -1; } + if (debug >= VERBOSE) + printk(KERN_DEBUG PFX "Watchdog started\n"); + return 0; } @@ -248,6 +276,9 @@ static int pcipcwd_stop(void) return -1; } + if (debug >= VERBOSE) + printk(KERN_DEBUG PFX "Watchdog stopped\n"); + return 0; } @@ -255,6 +286,10 @@ static int pcipcwd_keepalive(void) { /* Re-trigger watchdog by writing to port 0 */ outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */ + + if (debug >= DEBUG) + printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); + return 0; } @@ -270,6 +305,10 @@ static int pcipcwd_set_heartbeat(int t) send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); heartbeat = t; + if (debug >= VERBOSE) + printk(KERN_DEBUG PFX "New heartbeat: %d\n", + heartbeat); + return 0; } @@ -287,6 +326,10 @@ static int pcipcwd_get_status(int *status) panic(PFX "Temperature overheat trip!\n"); } + if (debug >= DEBUG) + printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n", + control_status); + return 0; } @@ -296,8 +339,17 @@ static int pcipcwd_clear_status(void) int msb; int reset_counter; + if (debug >= VERBOSE) + printk(KERN_INFO PFX "clearing watchdog trip status & LED\n"); + control_status = inb_p(pcipcwd_private.io_addr + 1); + if (debug >= DEBUG) { + printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); + printk(KERN_DEBUG PFX "sending: 0x%02x\n", + (control_status & WD_PCI_R2DS) | WD_PCI_WTRP); + } + /* clear trip status & LED and keep mode of relay 2 */ outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); @@ -306,6 +358,11 @@ static int pcipcwd_clear_status(void) reset_counter=0xff; send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); + if (debug >= DEBUG) { + printk(KERN_DEBUG PFX "reset count was: 0x%02x\n", + reset_counter); + } + return 0; } @@ -323,6 +380,11 @@ static int pcipcwd_get_temperature(int *temperature) */ *temperature = (*temperature * 9 / 5) + 32; + if (debug >= DEBUG) { + printk(KERN_DEBUG PFX "temperature is: %d F\n", + *temperature); + } + return 0; } @@ -457,6 +519,8 @@ static int pcipcwd_open(struct inode *inode, struct file *file) { /* /dev/watchdog can only be opened once */ if (test_and_set_bit(0, &is_active)) { + if (debug >= VERBOSE) + printk(KERN_ERR PFX "Attempt to open already opened device.\n"); return -EBUSY; } -- cgit v0.10.2 From ecba97d4aacf4e80c56eb73e39af0369cb8539a4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 Sep 2005 22:27:23 +0100 Subject: [PATCH] uml makefiles sanitized UML makefiles sanitized: - number of generated headers reduced to 2 (from user-offsets.c and kernel-offsets.c resp.). The rest is made constant and simply includes those two. - mk_... helpers are gone now that we don't need to generate these headers - arch/um/include2 removed since everything under arch/um/include/sysdep is constant now and symlink can point straight to source tree. - dependencies seriously simplified. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/um/Makefile b/arch/um/Makefile index 5b5af95..7af37e3 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -28,8 +28,6 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h -GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h - um-modes-$(CONFIG_MODE_TT) += tt um-modes-$(CONFIG_MODE_SKAS) += skas @@ -45,9 +43,7 @@ endif ARCH_INCLUDE := -I$(ARCH_DIR)/include ifneq ($(KBUILD_SRC),) -ARCH_INCLUDE += -I$(ARCH_DIR)/include2 ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include -MRPROPER_DIRS += $(ARCH_DIR)/include2 endif SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) @@ -87,10 +83,6 @@ CONFIG_KERNEL_HALF_GIGS ?= 0 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) -ifeq ($(CONFIG_MODE_SKAS), y) -$(SYS_HEADERS) : $(ARCH_DIR)/include/skas_ptregs.h -endif - .PHONY: linux all: linux @@ -111,7 +103,8 @@ else $(shell cd $(ARCH_DIR) && ln -sf Kconfig.$(SUBARCH) Kconfig.arch) endif -archprepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) +archprepare: $(ARCH_SYMLINKS) $(ARCH_DIR)/include/user_constants.h +prepare: $(ARCH_DIR)/include/kern_constants.h LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib @@ -146,15 +139,13 @@ endef #When cleaning we don't include .config, so we don't include #TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \ - $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \ - $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/Kconfig.arch + $(ARCH_DIR)/include/user_constants.h \ + $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \ $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os archclean: - $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util - $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/os-$(OS)/util @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -o -name '*.gcov' \) -type f -print | xargs rm -f @@ -180,9 +171,7 @@ $(ARCH_DIR)/include/sysdep: @echo ' SYMLINK $@' ifneq ($(KBUILD_SRC),) $(Q)mkdir -p $(ARCH_DIR)/include - $(Q)mkdir -p $(ARCH_DIR)/include2 - $(Q)ln -fsn sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep - $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include2/sysdep + $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep else $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep endif @@ -202,8 +191,6 @@ endef define filechk_gen-asm-offsets (set -e; \ - echo "#ifndef __ASM_OFFSETS_H__"; \ - echo "#define __ASM_OFFSETS_H__"; \ echo "/*"; \ echo " * DO NOT MODIFY."; \ echo " *"; \ @@ -212,8 +199,7 @@ define filechk_gen-asm-offsets echo " */"; \ echo ""; \ sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \ - echo ""; \ - echo "#endif" ) + echo ""; ) endef $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h @@ -222,50 +208,18 @@ $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h $(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c $(CC) $(USER_CFLAGS) -S -o $@ $< -$(ARCH_DIR)/user-offsets.h: $(ARCH_DIR)/user-offsets.s +$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s $(call filechk,gen-asm-offsets) -CLEAN_FILES += $(ARCH_DIR)/user-offsets.s $(ARCH_DIR)/user-offsets.h +CLEAN_FILES += $(ARCH_DIR)/user-offsets.s $(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \ - $(ARCH_SYMLINKS) \ - $(SYS_DIR)/sc.h \ - include/asm include/linux/version.h \ - include/config/MARKER \ - $(ARCH_DIR)/include/user_constants.h + archprepare $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $< -$(ARCH_DIR)/kernel-offsets.h: $(ARCH_DIR)/kernel-offsets.s +$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/kernel-offsets.s $(call filechk,gen-asm-offsets) -CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s $(ARCH_DIR)/kernel-offsets.h - -$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task - $(call filechk,gen_header) - -$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os-$(OS)/util/mk_user_constants - $(call filechk,gen_header) - -$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants - $(call filechk,gen_header) - -$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs - $(call filechk,gen_header) - -$(ARCH_DIR)/os-$(OS)/util/mk_user_constants: $(ARCH_DIR)/os-$(OS)/util FORCE ; - -$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \ - FORCE ; - -$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ; - -$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h $(ARCH_DIR)/kernel-offsets.h FORCE - $(Q)$(MAKE) $(build)=$@ - -$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE - $(Q)$(MAKE) $(build)=$@ - -$(ARCH_DIR)/os-$(OS)/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE - $(Q)$(MAKE) $(build)=$@ +CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s export SUBARCH USER_CFLAGS OS diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 1ab431a..2ee8a28 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -32,25 +32,3 @@ CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) ifneq ($(CONFIG_GPROF),y) ARCH_CFLAGS += -DUM_FASTCALL endif - -SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util -SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h - -prepare: $(SYS_HEADERS) - -$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc - $(call filechk,gen_header) - -$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread - $(call filechk,gen_header) - -$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE - $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ - -$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_DIR)/kernel-offsets.h FORCE - $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ - -$(SYS_UTIL_DIR): scripts_basic include/asm FORCE - $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) - -CLEAN_FILES += $(SYS_HEADERS) diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas index fd18ec5..ac35de5 100644 --- a/arch/um/Makefile-skas +++ b/arch/um/Makefile-skas @@ -10,5 +10,3 @@ CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT) CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT) LINK-$(CONFIG_GCOV) += $(GCOV_OPT) LINK-$(CONFIG_GPROF) += $(GPROF_OPT) - -GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 436abbb..4f118d5 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -12,24 +12,3 @@ CHECKFLAGS += -m64 ELF_ARCH := i386:x86-64 ELF_FORMAT := elf64-x86-64 - -SYS_UTIL_DIR := $(ARCH_DIR)/sys-x86_64/util -SYS_DIR := $(ARCH_DIR)/include/sysdep-x86_64 - -SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h - -prepare: $(SYS_HEADERS) - -$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc - $(call filechk,gen_header) - -$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread - $(call filechk,gen_header) - -$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE - $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ - -$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(GEN_HEADERS) $(ARCH_DIR)/kernel-offsets.h FORCE - $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ - -CLEAN_FILES += $(SYS_HEADERS) diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 782ac3a..356390d 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h @@ -1,7 +1,7 @@ /* for use by sys-$SUBARCH/kernel-offsets.c */ -OFFSET(TASK_REGS, task_struct, thread.regs); -OFFSET(TASK_PID, task_struct, pid); +OFFSET(HOST_TASK_REGS, task_struct, thread.regs); +OFFSET(HOST_TASK_PID, task_struct, pid); DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); diff --git a/arch/um/include/skas_ptregs.h b/arch/um/include/skas_ptregs.h new file mode 100644 index 0000000..73db19e --- /dev/null +++ b/arch/um/include/skas_ptregs.h @@ -0,0 +1,6 @@ +#ifndef __SKAS_PT_REGS_ +#define __SKAS_PT_REGS_ + +#include + +#endif diff --git a/arch/um/include/sysdep-i386/sc.h b/arch/um/include/sysdep-i386/sc.h new file mode 100644 index 0000000..c57d178 --- /dev/null +++ b/arch/um/include/sysdep-i386/sc.h @@ -0,0 +1,44 @@ +#ifndef __SYSDEP_I386_SC_H +#define __SYSDEP_I386_SC_H + +#include + +#define SC_OFFSET(sc, field) \ + *((unsigned long *) &(((char *) (sc))[HOST_##field])) +#define SC_FP_OFFSET(sc, field) \ + *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field])) +#define SC_FP_OFFSET_PTR(sc, field, type) \ + ((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field])) + +#define SC_IP(sc) SC_OFFSET(sc, SC_IP) +#define SC_SP(sc) SC_OFFSET(sc, SC_SP) +#define SC_FS(sc) SC_OFFSET(sc, SC_FS) +#define SC_GS(sc) SC_OFFSET(sc, SC_GS) +#define SC_DS(sc) SC_OFFSET(sc, SC_DS) +#define SC_ES(sc) SC_OFFSET(sc, SC_ES) +#define SC_SS(sc) SC_OFFSET(sc, SC_SS) +#define SC_CS(sc) SC_OFFSET(sc, SC_CS) +#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) +#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX) +#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX) +#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX) +#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX) +#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI) +#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI) +#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP) +#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO) +#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR) +#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2) +#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE) +#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) +#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW) +#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW) +#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG) +#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF) +#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL) +#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF) +#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL) +#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate) +#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void) + +#endif diff --git a/arch/um/include/sysdep-i386/thread.h b/arch/um/include/sysdep-i386/thread.h new file mode 100644 index 0000000..e2bd6ba --- /dev/null +++ b/arch/um/include/sysdep-i386/thread.h @@ -0,0 +1,11 @@ +#ifndef __UM_THREAD_H +#define __UM_THREAD_H + +#include + +#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS])) +#ifdef CONFIG_MODE_TT +#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) +#endif + +#endif diff --git a/arch/um/include/sysdep-x86_64/sc.h b/arch/um/include/sysdep-x86_64/sc.h new file mode 100644 index 0000000..a160d9f --- /dev/null +++ b/arch/um/include/sysdep-x86_64/sc.h @@ -0,0 +1,45 @@ +#ifndef __SYSDEP_X86_64_SC_H +#define __SYSDEP_X86_64_SC_H + +/* Copyright (C) 2003 - 2004 PathScale, Inc + * Released under the GPL + */ + +#include + +#define SC_OFFSET(sc, field) \ + *((unsigned long *) &(((char *) (sc))[HOST_##field])) + +#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX) +#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX) +#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX) +#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI) +#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI) +#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP) +#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX) +#define SC_R8(sc) SC_OFFSET(sc, SC_R8) +#define SC_R9(sc) SC_OFFSET(sc, SC_R9) +#define SC_R10(sc) SC_OFFSET(sc, SC_R10) +#define SC_R11(sc) SC_OFFSET(sc, SC_R11) +#define SC_R12(sc) SC_OFFSET(sc, SC_R12) +#define SC_R13(sc) SC_OFFSET(sc, SC_R13) +#define SC_R14(sc) SC_OFFSET(sc, SC_R14) +#define SC_R15(sc) SC_OFFSET(sc, SC_R15) +#define SC_IP(sc) SC_OFFSET(sc, SC_IP) +#define SC_SP(sc) SC_OFFSET(sc, SC_SP) +#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2) +#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR) +#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO) +#define SC_CS(sc) SC_OFFSET(sc, SC_CS) +#define SC_FS(sc) SC_OFFSET(sc, SC_FS) +#define SC_GS(sc) SC_OFFSET(sc, SC_GS) +#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) +#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) +#if 0 +#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX) +#define SC_DS(sc) SC_OFFSET(sc, SC_DS) +#define SC_ES(sc) SC_OFFSET(sc, SC_ES) +#define SC_SS(sc) SC_OFFSET(sc, SC_SS) +#endif + +#endif diff --git a/arch/um/include/sysdep-x86_64/thread.h b/arch/um/include/sysdep-x86_64/thread.h new file mode 100644 index 0000000..6a76a7f --- /dev/null +++ b/arch/um/include/sysdep-x86_64/thread.h @@ -0,0 +1,10 @@ +#ifndef __UM_THREAD_H +#define __UM_THREAD_H + +#include + +#ifdef CONFIG_MODE_TT +#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID])) +#endif + +#endif diff --git a/arch/um/include/task.h b/arch/um/include/task.h new file mode 100644 index 0000000..6375ba7 --- /dev/null +++ b/arch/um/include/task.h @@ -0,0 +1,9 @@ +#ifndef __TASK_H +#define __TASK_H + +#include + +#define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) +#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) + +#endif diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index db36c7c..8de471b 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -6,8 +6,6 @@ obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ syscall.o tlb.o trap_user.o uaccess.o -subdir- := util - USER_OBJS := process.o clone.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile deleted file mode 100644 index f7b7eba..0000000 --- a/arch/um/kernel/skas/util/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -hostprogs-y := mk_ptregs -always := $(hostprogs-y) - -mk_ptregs-objs := mk_ptregs-$(SUBARCH).o -HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c deleted file mode 100644 index 1f96e1e..0000000 --- a/arch/um/kernel/skas/util/mk_ptregs-i386.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include - -#define SHOW(name) printf("#define %s %d\n", #name, name) - -int main(int argc, char **argv) -{ - printf("/* Automatically generated by " - "arch/um/kernel/skas/util/mk_ptregs */\n"); - printf("\n"); - printf("#ifndef __SKAS_PT_REGS_\n"); - printf("#define __SKAS_PT_REGS_\n"); - printf("\n"); - SHOW(HOST_FRAME_SIZE); - SHOW(HOST_FP_SIZE); - SHOW(HOST_XFP_SIZE); - - SHOW(HOST_IP); - SHOW(HOST_SP); - SHOW(HOST_EFLAGS); - SHOW(HOST_EAX); - SHOW(HOST_EBX); - SHOW(HOST_ECX); - SHOW(HOST_EDX); - SHOW(HOST_ESI); - SHOW(HOST_EDI); - SHOW(HOST_EBP); - SHOW(HOST_CS); - SHOW(HOST_SS); - SHOW(HOST_DS); - SHOW(HOST_FS); - SHOW(HOST_ES); - SHOW(HOST_GS); - - printf("\n"); - printf("#endif\n"); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c deleted file mode 100644 index 5fccbfe3..0000000 --- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include -#include - -#define SHOW(name) \ - printf("#define %s (%d / sizeof(unsigned long))\n", #name, name) - -int main(int argc, char **argv) -{ - printf("/* Automatically generated by " - "arch/um/kernel/skas/util/mk_ptregs */\n"); - printf("\n"); - printf("#ifndef __SKAS_PT_REGS_\n"); - printf("#define __SKAS_PT_REGS_\n"); - SHOW(HOST_FRAME_SIZE); - SHOW(HOST_RBX); - SHOW(HOST_RCX); - SHOW(HOST_RDI); - SHOW(HOST_RSI); - SHOW(HOST_RDX); - SHOW(HOST_RBP); - SHOW(HOST_RAX); - SHOW(HOST_R8); - SHOW(HOST_R9); - SHOW(HOST_R10); - SHOW(HOST_R11); - SHOW(HOST_R12); - SHOW(HOST_R13); - SHOW(HOST_R14); - SHOW(HOST_R15); - SHOW(HOST_ORIG_RAX); - SHOW(HOST_CS); - SHOW(HOST_SS); - SHOW(HOST_EFLAGS); -#if 0 - SHOW(HOST_FS); - SHOW(HOST_GS); - SHOW(HOST_DS); - SHOW(HOST_ES); -#endif - - SHOW(HOST_IP); - SHOW(HOST_SP); - printf("#define HOST_FP_SIZE 0\n"); - printf("#define HOST_XFP_SIZE 0\n"); - printf("\n"); - printf("\n"); - printf("#endif\n"); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index ab33cb3..5a99dd3 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -12,7 +12,7 @@ #include "init.h" #include "elf_user.h" #include "mem_user.h" -#include +#include /* Use the one from the kernel - the host may miss it, if having old headers. */ #if UM_ELF_CLASS == UM_ELFCLASS32 diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile deleted file mode 100644 index 9778aed..0000000 --- a/arch/um/os-Linux/util/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -hostprogs-y := mk_user_constants -always := $(hostprogs-y) - -HOSTCFLAGS_mk_user_constants.o := -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c deleted file mode 100644 index 4838f30..0000000 --- a/arch/um/os-Linux/util/mk_user_constants.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -int main(int argc, char **argv) -{ - printf("/*\n"); - printf(" * Generated by mk_user_constants\n"); - printf(" */\n"); - printf("\n"); - printf("#ifndef __UM_USER_CONSTANTS_H\n"); - printf("#define __UM_USER_CONSTANTS_H\n"); - printf("\n"); - /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on - * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on - * both x86_64 and i386. - */ - printf("#define UM_FRAME_SIZE %d\n", __UM_FRAME_SIZE); - - printf("\n"); - printf("#endif\n"); - - return(0); -} diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 4ca2a22..6dfeb70f 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -18,6 +18,4 @@ module.c-dir = kernel $(obj)/stub_segv.o : _c_flags = $(call unprofile,$(CFLAGS)) -subdir- := util - include arch/um/scripts/Makefile.unmap diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/sys-i386/kernel-offsets.c index a1070af..35db850 100644 --- a/arch/um/sys-i386/kernel-offsets.c +++ b/arch/um/sys-i386/kernel-offsets.c @@ -18,9 +18,9 @@ void foo(void) { - OFFSET(TASK_DEBUGREGS, task_struct, thread.arch.debugregs); + OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs); #ifdef CONFIG_MODE_TT - OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); + OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); #endif #include } diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 3ceaabc..677fc26 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c @@ -7,47 +7,48 @@ #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#define DEFINE_LONGS(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) + #define OFFSET(sym, str, mem) \ DEFINE(sym, offsetof(struct str, mem)); void foo(void) { - OFFSET(SC_IP, sigcontext, eip); - OFFSET(SC_SP, sigcontext, esp); - OFFSET(SC_FS, sigcontext, fs); - OFFSET(SC_GS, sigcontext, gs); - OFFSET(SC_DS, sigcontext, ds); - OFFSET(SC_ES, sigcontext, es); - OFFSET(SC_SS, sigcontext, ss); - OFFSET(SC_CS, sigcontext, cs); - OFFSET(SC_EFLAGS, sigcontext, eflags); - OFFSET(SC_EAX, sigcontext, eax); - OFFSET(SC_EBX, sigcontext, ebx); - OFFSET(SC_ECX, sigcontext, ecx); - OFFSET(SC_EDX, sigcontext, edx); - OFFSET(SC_EDI, sigcontext, edi); - OFFSET(SC_ESI, sigcontext, esi); - OFFSET(SC_EBP, sigcontext, ebp); - OFFSET(SC_TRAPNO, sigcontext, trapno); - OFFSET(SC_ERR, sigcontext, err); - OFFSET(SC_CR2, sigcontext, cr2); - OFFSET(SC_FPSTATE, sigcontext, fpstate); - OFFSET(SC_SIGMASK, sigcontext, oldmask); - OFFSET(SC_FP_CW, _fpstate, cw); - OFFSET(SC_FP_SW, _fpstate, sw); - OFFSET(SC_FP_TAG, _fpstate, tag); - OFFSET(SC_FP_IPOFF, _fpstate, ipoff); - OFFSET(SC_FP_CSSEL, _fpstate, cssel); - OFFSET(SC_FP_DATAOFF, _fpstate, dataoff); - OFFSET(SC_FP_DATASEL, _fpstate, datasel); - OFFSET(SC_FP_ST, _fpstate, _st); - OFFSET(SC_FXSR_ENV, _fpstate, _fxsr_env); + OFFSET(HOST_SC_IP, sigcontext, eip); + OFFSET(HOST_SC_SP, sigcontext, esp); + OFFSET(HOST_SC_FS, sigcontext, fs); + OFFSET(HOST_SC_GS, sigcontext, gs); + OFFSET(HOST_SC_DS, sigcontext, ds); + OFFSET(HOST_SC_ES, sigcontext, es); + OFFSET(HOST_SC_SS, sigcontext, ss); + OFFSET(HOST_SC_CS, sigcontext, cs); + OFFSET(HOST_SC_EFLAGS, sigcontext, eflags); + OFFSET(HOST_SC_EAX, sigcontext, eax); + OFFSET(HOST_SC_EBX, sigcontext, ebx); + OFFSET(HOST_SC_ECX, sigcontext, ecx); + OFFSET(HOST_SC_EDX, sigcontext, edx); + OFFSET(HOST_SC_EDI, sigcontext, edi); + OFFSET(HOST_SC_ESI, sigcontext, esi); + OFFSET(HOST_SC_EBP, sigcontext, ebp); + OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); + OFFSET(HOST_SC_ERR, sigcontext, err); + OFFSET(HOST_SC_CR2, sigcontext, cr2); + OFFSET(HOST_SC_FPSTATE, sigcontext, fpstate); + OFFSET(HOST_SC_SIGMASK, sigcontext, oldmask); + OFFSET(HOST_SC_FP_CW, _fpstate, cw); + OFFSET(HOST_SC_FP_SW, _fpstate, sw); + OFFSET(HOST_SC_FP_TAG, _fpstate, tag); + OFFSET(HOST_SC_FP_IPOFF, _fpstate, ipoff); + OFFSET(HOST_SC_FP_CSSEL, _fpstate, cssel); + OFFSET(HOST_SC_FP_DATAOFF, _fpstate, dataoff); + OFFSET(HOST_SC_FP_DATASEL, _fpstate, datasel); + OFFSET(HOST_SC_FP_ST, _fpstate, _st); + OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); - DEFINE(HOST_FRAME_SIZE, FRAME_SIZE); - DEFINE(HOST_FP_SIZE, - sizeof(struct user_i387_struct) / sizeof(unsigned long)); - DEFINE(HOST_XFP_SIZE, - sizeof(struct user_fxsr_struct) / sizeof(unsigned long)); + DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); + DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); + DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); DEFINE(HOST_IP, EIP); DEFINE(HOST_SP, UESP); @@ -65,5 +66,5 @@ void foo(void) DEFINE(HOST_FS, FS); DEFINE(HOST_ES, ES); DEFINE(HOST_GS, GS); - DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct)); + DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); } diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile deleted file mode 100644 index bf61afd..0000000 --- a/arch/um/sys-i386/util/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -hostprogs-y := mk_sc mk_thread -always := $(hostprogs-y) - -HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um -HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c deleted file mode 100644 index 04c0d73..0000000 --- a/arch/um/sys-i386/util/mk_sc.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#define SC_OFFSET(name, field) \ - printf("#define " #name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ - name) - -#define SC_FP_OFFSET(name, field) \ - printf("#define " #name \ - "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ - name) - -#define SC_FP_OFFSET_PTR(name, field, type) \ - printf("#define " #name \ - "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\ - name) - -int main(int argc, char **argv) -{ - SC_OFFSET(SC_IP, eip); - SC_OFFSET(SC_SP, esp); - SC_OFFSET(SC_FS, fs); - SC_OFFSET(SC_GS, gs); - SC_OFFSET(SC_DS, ds); - SC_OFFSET(SC_ES, es); - SC_OFFSET(SC_SS, ss); - SC_OFFSET(SC_CS, cs); - SC_OFFSET(SC_EFLAGS, eflags); - SC_OFFSET(SC_EAX, eax); - SC_OFFSET(SC_EBX, ebx); - SC_OFFSET(SC_ECX, ecx); - SC_OFFSET(SC_EDX, edx); - SC_OFFSET(SC_EDI, edi); - SC_OFFSET(SC_ESI, esi); - SC_OFFSET(SC_EBP, ebp); - SC_OFFSET(SC_TRAPNO, trapno); - SC_OFFSET(SC_ERR, err); - SC_OFFSET(SC_CR2, cr2); - SC_OFFSET(SC_FPSTATE, fpstate); - SC_OFFSET(SC_SIGMASK, oldmask); - SC_FP_OFFSET(SC_FP_CW, cw); - SC_FP_OFFSET(SC_FP_SW, sw); - SC_FP_OFFSET(SC_FP_TAG, tag); - SC_FP_OFFSET(SC_FP_IPOFF, ipoff); - SC_FP_OFFSET(SC_FP_CSSEL, cssel); - SC_FP_OFFSET(SC_FP_DATAOFF, dataoff); - SC_FP_OFFSET(SC_FP_DATASEL, datasel); - SC_FP_OFFSET_PTR(SC_FP_ST, _st, "struct _fpstate"); - SC_FP_OFFSET_PTR(SC_FXSR_ENV, _fxsr_env, "void"); - return(0); -} diff --git a/arch/um/sys-i386/util/mk_thread.c b/arch/um/sys-i386/util/mk_thread.c deleted file mode 100644 index 7470d0d..0000000 --- a/arch/um/sys-i386/util/mk_thread.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include - -int main(int argc, char **argv) -{ - printf("/*\n"); - printf(" * Generated by mk_thread\n"); - printf(" */\n"); - printf("\n"); - printf("#ifndef __UM_THREAD_H\n"); - printf("#define __UM_THREAD_H\n"); - printf("\n"); - printf("#define TASK_DEBUGREGS(task) ((unsigned long *) " - "&(((char *) (task))[%d]))\n", TASK_DEBUGREGS); -#ifdef TASK_EXTERN_PID - printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n", - TASK_EXTERN_PID); -#endif - printf("\n"); - printf("#endif\n"); - return(0); -} diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index f0ab574d..06c3633 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -29,6 +29,4 @@ module.c-dir = kernel $(obj)/stub_segv.o: _c_flags = $(call unprofile,$(CFLAGS)) -subdir- := util - include arch/um/scripts/Makefile.unmap diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/sys-x86_64/kernel-offsets.c index 998541e..bfcb104 100644 --- a/arch/um/sys-x86_64/kernel-offsets.c +++ b/arch/um/sys-x86_64/kernel-offsets.c @@ -19,7 +19,7 @@ void foo(void) { #ifdef CONFIG_MODE_TT - OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); + OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); #endif #include } diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 513d17c..5a585bf 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -16,71 +16,76 @@ typedef __u32 u32; #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#define DEFINE_LONGS(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) + #define OFFSET(sym, str, mem) \ DEFINE(sym, offsetof(struct str, mem)); void foo(void) { - OFFSET(SC_RBX, sigcontext, rbx); - OFFSET(SC_RCX, sigcontext, rcx); - OFFSET(SC_RDX, sigcontext, rdx); - OFFSET(SC_RSI, sigcontext, rsi); - OFFSET(SC_RDI, sigcontext, rdi); - OFFSET(SC_RBP, sigcontext, rbp); - OFFSET(SC_RAX, sigcontext, rax); - OFFSET(SC_R8, sigcontext, r8); - OFFSET(SC_R9, sigcontext, r9); - OFFSET(SC_R10, sigcontext, r10); - OFFSET(SC_R11, sigcontext, r11); - OFFSET(SC_R12, sigcontext, r12); - OFFSET(SC_R13, sigcontext, r13); - OFFSET(SC_R14, sigcontext, r14); - OFFSET(SC_R15, sigcontext, r15); - OFFSET(SC_IP, sigcontext, rip); - OFFSET(SC_SP, sigcontext, rsp); - OFFSET(SC_CR2, sigcontext, cr2); - OFFSET(SC_ERR, sigcontext, err); - OFFSET(SC_TRAPNO, sigcontext, trapno); - OFFSET(SC_CS, sigcontext, cs); - OFFSET(SC_FS, sigcontext, fs); - OFFSET(SC_GS, sigcontext, gs); - OFFSET(SC_EFLAGS, sigcontext, eflags); - OFFSET(SC_SIGMASK, sigcontext, oldmask); + OFFSET(HOST_SC_RBX, sigcontext, rbx); + OFFSET(HOST_SC_RCX, sigcontext, rcx); + OFFSET(HOST_SC_RDX, sigcontext, rdx); + OFFSET(HOST_SC_RSI, sigcontext, rsi); + OFFSET(HOST_SC_RDI, sigcontext, rdi); + OFFSET(HOST_SC_RBP, sigcontext, rbp); + OFFSET(HOST_SC_RAX, sigcontext, rax); + OFFSET(HOST_SC_R8, sigcontext, r8); + OFFSET(HOST_SC_R9, sigcontext, r9); + OFFSET(HOST_SC_R10, sigcontext, r10); + OFFSET(HOST_SC_R11, sigcontext, r11); + OFFSET(HOST_SC_R12, sigcontext, r12); + OFFSET(HOST_SC_R13, sigcontext, r13); + OFFSET(HOST_SC_R14, sigcontext, r14); + OFFSET(HOST_SC_R15, sigcontext, r15); + OFFSET(HOST_SC_IP, sigcontext, rip); + OFFSET(HOST_SC_SP, sigcontext, rsp); + OFFSET(HOST_SC_CR2, sigcontext, cr2); + OFFSET(HOST_SC_ERR, sigcontext, err); + OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); + OFFSET(HOST_SC_CS, sigcontext, cs); + OFFSET(HOST_SC_FS, sigcontext, fs); + OFFSET(HOST_SC_GS, sigcontext, gs); + OFFSET(HOST_SC_EFLAGS, sigcontext, eflags); + OFFSET(HOST_SC_SIGMASK, sigcontext, oldmask); #if 0 - OFFSET(SC_ORIG_RAX, sigcontext, orig_rax); - OFFSET(SC_DS, sigcontext, ds); - OFFSET(SC_ES, sigcontext, es); - OFFSET(SC_SS, sigcontext, ss); + OFFSET(HOST_SC_ORIG_RAX, sigcontext, orig_rax); + OFFSET(HOST_SC_DS, sigcontext, ds); + OFFSET(HOST_SC_ES, sigcontext, es); + OFFSET(HOST_SC_SS, sigcontext, ss); #endif - DEFINE(HOST_FRAME_SIZE, FRAME_SIZE); - DEFINE(HOST_RBX, RBX); - DEFINE(HOST_RCX, RCX); - DEFINE(HOST_RDI, RDI); - DEFINE(HOST_RSI, RSI); - DEFINE(HOST_RDX, RDX); - DEFINE(HOST_RBP, RBP); - DEFINE(HOST_RAX, RAX); - DEFINE(HOST_R8, R8); - DEFINE(HOST_R9, R9); - DEFINE(HOST_R10, R10); - DEFINE(HOST_R11, R11); - DEFINE(HOST_R12, R12); - DEFINE(HOST_R13, R13); - DEFINE(HOST_R14, R14); - DEFINE(HOST_R15, R15); - DEFINE(HOST_ORIG_RAX, ORIG_RAX); - DEFINE(HOST_CS, CS); - DEFINE(HOST_SS, SS); - DEFINE(HOST_EFLAGS, EFLAGS); + DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); + DEFINE(HOST_FP_SIZE, 0); + DEFINE(HOST_XFP_SIZE, 0); + DEFINE_LONGS(HOST_RBX, RBX); + DEFINE_LONGS(HOST_RCX, RCX); + DEFINE_LONGS(HOST_RDI, RDI); + DEFINE_LONGS(HOST_RSI, RSI); + DEFINE_LONGS(HOST_RDX, RDX); + DEFINE_LONGS(HOST_RBP, RBP); + DEFINE_LONGS(HOST_RAX, RAX); + DEFINE_LONGS(HOST_R8, R8); + DEFINE_LONGS(HOST_R9, R9); + DEFINE_LONGS(HOST_R10, R10); + DEFINE_LONGS(HOST_R11, R11); + DEFINE_LONGS(HOST_R12, R12); + DEFINE_LONGS(HOST_R13, R13); + DEFINE_LONGS(HOST_R14, R14); + DEFINE_LONGS(HOST_R15, R15); + DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX); + DEFINE_LONGS(HOST_CS, CS); + DEFINE_LONGS(HOST_SS, SS); + DEFINE_LONGS(HOST_EFLAGS, EFLAGS); #if 0 - DEFINE(HOST_FS, FS); - DEFINE(HOST_GS, GS); - DEFINE(HOST_DS, DS); - DEFINE(HOST_ES, ES); + DEFINE_LONGS(HOST_FS, FS); + DEFINE_LONGS(HOST_GS, GS); + DEFINE_LONGS(HOST_DS, DS); + DEFINE_LONGS(HOST_ES, ES); #endif - DEFINE(HOST_IP, RIP); - DEFINE(HOST_SP, RSP); - DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct)); + DEFINE_LONGS(HOST_IP, RIP); + DEFINE_LONGS(HOST_SP, RSP); + DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); } diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile deleted file mode 100644 index 75b052c..0000000 --- a/arch/um/sys-x86_64/util/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2003 - 2004 Pathscale, Inc -# Released under the GPL - -hostprogs-y := mk_sc mk_thread -always := $(hostprogs-y) - -HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um -HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c deleted file mode 100644 index 7619bc3..0000000 --- a/arch/um/sys-x86_64/util/mk_sc.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2003 - 2004 PathScale, Inc - * Released under the GPL - */ - -#include -#include - -#define SC_OFFSET(name) \ - printf("#define " #name \ - "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\ - name) - -int main(int argc, char **argv) -{ - SC_OFFSET(SC_RBX); - SC_OFFSET(SC_RCX); - SC_OFFSET(SC_RDX); - SC_OFFSET(SC_RSI); - SC_OFFSET(SC_RDI); - SC_OFFSET(SC_RBP); - SC_OFFSET(SC_RAX); - SC_OFFSET(SC_R8); - SC_OFFSET(SC_R9); - SC_OFFSET(SC_R10); - SC_OFFSET(SC_R11); - SC_OFFSET(SC_R12); - SC_OFFSET(SC_R13); - SC_OFFSET(SC_R14); - SC_OFFSET(SC_R15); - SC_OFFSET(SC_IP); - SC_OFFSET(SC_SP); - SC_OFFSET(SC_CR2); - SC_OFFSET(SC_ERR); - SC_OFFSET(SC_TRAPNO); - SC_OFFSET(SC_CS); - SC_OFFSET(SC_FS); - SC_OFFSET(SC_GS); - SC_OFFSET(SC_EFLAGS); - SC_OFFSET(SC_SIGMASK); -#if 0 - SC_OFFSET(SC_ORIG_RAX); - SC_OFFSET(SC_DS); - SC_OFFSET(SC_ES); - SC_OFFSET(SC_SS); -#endif - return(0); -} diff --git a/arch/um/sys-x86_64/util/mk_thread.c b/arch/um/sys-x86_64/util/mk_thread.c deleted file mode 100644 index 1551739..0000000 --- a/arch/um/sys-x86_64/util/mk_thread.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -int main(int argc, char **argv) -{ - printf("/*\n"); - printf(" * Generated by mk_thread\n"); - printf(" */\n"); - printf("\n"); - printf("#ifndef __UM_THREAD_H\n"); - printf("#define __UM_THREAD_H\n"); - printf("\n"); -#ifdef TASK_EXTERN_PID - printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n", - TASK_EXTERN_PID); -#endif - printf("\n"); - printf("#endif\n"); - return(0); -} diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile deleted file mode 100644 index 4c7551c..0000000 --- a/arch/um/util/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -hostprogs-y := mk_task mk_constants -always := $(hostprogs-y) - -HOSTCFLAGS_mk_task.o := -I$(objtree)/arch/um -HOSTCFLAGS_mk_constants.o := -I$(objtree)/arch/um diff --git a/arch/um/util/mk_constants.c b/arch/um/util/mk_constants.c deleted file mode 100644 index ab217be..0000000 --- a/arch/um/util/mk_constants.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -#define SHOW_INT(sym) printf("#define %s %d\n", #sym, sym) -#define SHOW_STR(sym) printf("#define %s %s\n", #sym, sym) - -int main(int argc, char **argv) -{ - printf("/*\n"); - printf(" * Generated by mk_constants\n"); - printf(" */\n"); - printf("\n"); - printf("#ifndef __UM_CONSTANTS_H\n"); - printf("#define __UM_CONSTANTS_H\n"); - printf("\n"); - - SHOW_INT(UM_KERN_PAGE_SIZE); - - SHOW_STR(UM_KERN_EMERG); - SHOW_STR(UM_KERN_ALERT); - SHOW_STR(UM_KERN_CRIT); - SHOW_STR(UM_KERN_ERR); - SHOW_STR(UM_KERN_WARNING); - SHOW_STR(UM_KERN_NOTICE); - SHOW_STR(UM_KERN_INFO); - SHOW_STR(UM_KERN_DEBUG); - - SHOW_INT(UM_NSEC_PER_SEC); - printf("\n"); - printf("#endif\n"); - return(0); -} diff --git a/arch/um/util/mk_task.c b/arch/um/util/mk_task.c deleted file mode 100644 index 36c9606..0000000 --- a/arch/um/util/mk_task.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -void print_ptr(char *name, char *type, int offset) -{ - printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type, - offset); -} - -void print(char *name, char *type, int offset) -{ - printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type, - offset); -} - -int main(int argc, char **argv) -{ - printf("/*\n"); - printf(" * Generated by mk_task\n"); - printf(" */\n"); - printf("\n"); - printf("#ifndef __TASK_H\n"); - printf("#define __TASK_H\n"); - printf("\n"); - print_ptr("TASK_REGS", "union uml_pt_regs", TASK_REGS); - print("TASK_PID", "int", TASK_PID); - printf("\n"); - printf("#endif\n"); - return(0); -} -- cgit v0.10.2 From 666002218d59db271e5c1ede1d80227170c51987 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 Sep 2005 22:32:57 +0100 Subject: [PATCH] proc_mkdir() should be used to create procfs directories A bunch of create_proc_dir_entry() calls creating directories had crept in since the last sweep; converted to proc_mkdir(). Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 6ba48f3..041bb47 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -376,7 +376,7 @@ static int __init drm_core_init(void) goto err_p2; } - drm_proc_root = create_proc_entry("dri", S_IFDIR, NULL); + drm_proc_root = proc_mkdir("dri", NULL); if (!drm_proc_root) { DRM_ERROR("Cannot create /proc/dri\n"); ret = -1; diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 32d2bb9..9779610 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c @@ -95,7 +95,7 @@ int drm_proc_init(drm_device_t *dev, int minor, char name[64]; sprintf(name, "%d", minor); - *dev_root = create_proc_entry(name, S_IFDIR, root); + *dev_root = proc_mkdir(name, root); if (!*dev_root) { DRM_ERROR("Cannot create /proc/dri/%s\n", name); return -1; diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index e1f0d87..0b0ea26 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -287,12 +287,12 @@ divert_dev_init(void) init_waitqueue_head(&rd_queue); #ifdef CONFIG_PROC_FS - isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net); + isdn_proc_entry = proc_mkdir("net/isdn", NULL); if (!isdn_proc_entry) return (-1); isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry); if (!isdn_divert_entry) { - remove_proc_entry("isdn", proc_net); + remove_proc_entry("net/isdn", NULL); return (-1); } isdn_divert_entry->proc_fops = &isdn_fops; @@ -312,7 +312,7 @@ divert_dev_deinit(void) #ifdef CONFIG_PROC_FS remove_proc_entry("divert", isdn_proc_entry); - remove_proc_entry("isdn", proc_net); + remove_proc_entry("net/isdn", NULL); #endif /* CONFIG_PROC_FS */ return (0); diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c index 7fdf8ae..27204f4 100644 --- a/drivers/isdn/hardware/eicon/diva_didd.c +++ b/drivers/isdn/hardware/eicon/diva_didd.c @@ -30,8 +30,6 @@ static char *DRIVERNAME = static char *DRIVERLNAME = "divadidd"; char *DRIVERRELEASE_DIDD = "2.0"; -static char *main_proc_dir = "eicon"; - MODULE_DESCRIPTION("DIDD table driver for diva drivers"); MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); MODULE_SUPPORTED_DEVICE("Eicon diva drivers"); @@ -89,7 +87,7 @@ proc_read(char *page, char **start, off_t off, int count, int *eof, static int DIVA_INIT_FUNCTION create_proc(void) { - proc_net_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net); + proc_net_eicon = proc_mkdir("net/eicon", NULL); if (proc_net_eicon) { if ((proc_didd = @@ -105,7 +103,7 @@ static int DIVA_INIT_FUNCTION create_proc(void) static void DIVA_EXIT_FUNCTION remove_proc(void) { remove_proc_entry(DRIVERLNAME, proc_net_eicon); - remove_proc_entry(main_proc_dir, proc_net); + remove_proc_entry("net/eicon", NULL); } static int DIVA_INIT_FUNCTION divadidd_init(void) diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index b643558..c12efa6 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -381,7 +381,7 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a) char tmp[16]; sprintf(tmp, "%s%d", adapter_dir_name, a->controller); - if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_eicon))) + if (!(de = proc_mkdir(tmp, proc_net_eicon))) return (0); a->proc_adapter_dir = (void *) de; diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 5da507e..639582f 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -394,7 +394,7 @@ hysdn_procconf_init(void) hysdn_card *card; uchar conf_name[20]; - hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net); + hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net); if (!hysdn_proc_entry) { printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); return (-1); diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 8c08b7f..b7ec9bf 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -1397,7 +1397,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam) static void proc_cpia_create(void) { - cpia_proc_root = create_proc_entry("cpia", S_IFDIR, NULL); + cpia_proc_root = proc_mkdir("cpia", NULL); if (cpia_proc_root) cpia_proc_root->owner = THIS_MODULE; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 32d5fab..a2c4dd4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -99,7 +99,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*); #ifdef CONFIG_PROC_FS -#define IBMVETH_PROC_DIR "ibmveth" +#define IBMVETH_PROC_DIR "net/ibmveth" static struct proc_dir_entry *ibmveth_proc_dir; #endif @@ -1010,7 +1010,7 @@ static int __devexit ibmveth_remove(struct vio_dev *dev) #ifdef CONFIG_PROC_FS static void ibmveth_proc_register_driver(void) { - ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net); + ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL); if (ibmveth_proc_dir) { SET_MODULE_OWNER(ibmveth_proc_dir); } @@ -1018,7 +1018,7 @@ static void ibmveth_proc_register_driver(void) static void ibmveth_proc_unregister_driver(void) { - remove_proc_entry(IBMVETH_PROC_DIR, proc_net); + remove_proc_entry(IBMVETH_PROC_DIR, NULL); } static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 6d9de62..651c5a6 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -1875,11 +1875,11 @@ static int __init vlsi_mod_init(void) sirpulse = !!sirpulse; - /* create_proc_entry returns NULL if !CONFIG_PROC_FS. + /* proc_mkdir returns NULL if !CONFIG_PROC_FS. * Failure to create the procfs entry is handled like running * without procfs - it's not required for the driver to work. */ - vlsi_proc_root = create_proc_entry(PROC_DIR, S_IFDIR, NULL); + vlsi_proc_root = proc_mkdir(PROC_DIR, NULL); if (vlsi_proc_root) { /* protect registered procdir against module removal. * Because we are in the module init path there's no race diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 82f236c..a842ecc 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -1070,7 +1070,7 @@ static int __init pppoe_proc_init(void) { struct proc_dir_entry *p; - p = create_proc_entry("pppoe", S_IRUGO, proc_net); + p = create_proc_entry("net/pppoe", S_IRUGO, NULL); if (!p) return -ENOMEM; @@ -1142,7 +1142,7 @@ static void __exit pppoe_exit(void) dev_remove_pack(&pppoes_ptype); dev_remove_pack(&pppoed_ptype); unregister_netdevice_notifier(&pppoe_notifier); - remove_proc_entry("pppoe", proc_net); + remove_proc_entry("net/pppoe", NULL); proto_unregister(&pppoe_sk_proto); } diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 2e72d79..b18c92c 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -235,7 +235,7 @@ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); * Extern Function Prototypes * ******************************************************************************/ -static const char SKRootName[] = "sk98lin"; +static const char SKRootName[] = "net/sk98lin"; static struct proc_dir_entry *pSkRootDir; extern struct file_operations sk_proc_fops; @@ -5242,20 +5242,20 @@ static int __init skge_init(void) { int error; - pSkRootDir = proc_mkdir(SKRootName, proc_net); + pSkRootDir = proc_mkdir(SKRootName, NULL); if (pSkRootDir) pSkRootDir->owner = THIS_MODULE; error = pci_register_driver(&skge_driver); if (error) - proc_net_remove(SKRootName); + remove_proc_entry(SKRootName, NULL); return error; } static void __exit skge_exit(void) { pci_unregister_driver(&skge_driver); - proc_net_remove(SKRootName); + remove_proc_entry(SKRootName, NULL); } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4d09a6e..ad94367 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2849,8 +2849,7 @@ sg_proc_init(void) struct proc_dir_entry *pdep; struct sg_proc_leaf * leaf; - sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname, - S_IFDIR | S_IRUGO | S_IXUGO, NULL); + sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL); if (!sg_proc_sgp) return 1; for (k = 0; k < num_leaves; ++k) { diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 4a5857c..0bc0b12 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -1148,7 +1148,7 @@ vicam_write_proc_gain(struct file *file, const char *buffer, static void vicam_create_proc_root(void) { - vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0); + vicam_proc_root = proc_mkdir("video/vicam", NULL); if (vicam_proc_root) vicam_proc_root->owner = THIS_MODULE; @@ -1181,7 +1181,7 @@ vicam_create_proc_entry(struct vicam_camera *cam) sprintf(name, "video%d", cam->vdev.minor); - cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root); + cam->proc_dir = proc_mkdir(name, vicam_proc_root); if ( !cam->proc_dir ) return; // FIXME: We should probably return an error here diff --git a/net/core/pktgen.c b/net/core/pktgen.c index ef430b1e..b7f2d65 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -186,7 +186,7 @@ /* Used to help with determining the pkts on receive */ #define PKTGEN_MAGIC 0xbe9be955 -#define PG_PROC_DIR "pktgen" +#define PG_PROC_DIR "net/pktgen" #define MAX_CFLOWS 65536 @@ -1476,18 +1476,7 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer, static int create_proc_dir(void) { - int len; - /* does proc_dir already exists */ - len = strlen(PG_PROC_DIR); - - for (pg_proc_dir = proc_net->subdir; pg_proc_dir; pg_proc_dir=pg_proc_dir->next) { - if ((pg_proc_dir->namelen == len) && - (! memcmp(pg_proc_dir->name, PG_PROC_DIR, len))) - break; - } - - if (!pg_proc_dir) - pg_proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net); + pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL); if (!pg_proc_dir) return -ENODEV; @@ -1497,7 +1486,7 @@ static int create_proc_dir(void) static int remove_proc_dir(void) { - remove_proc_entry(PG_PROC_DIR, proc_net); + remove_proc_entry(PG_PROC_DIR, NULL); return 0; } @@ -2908,7 +2897,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) pkt_dev->udp_dst_max = 9; strncpy(pkt_dev->ifname, ifname, 31); - sprintf(pkt_dev->fname, "net/%s/%s", PG_PROC_DIR, ifname); + sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname); if (! pktgen_setup_dev(pkt_dev)) { printk("pktgen: ERROR: pktgen_setup_dev failed.\n"); @@ -2981,7 +2970,7 @@ static int pktgen_create_thread(const char* name, int cpu) spin_lock_init(&t->if_lock); t->cpu = cpu; - sprintf(t->fname, "net/%s/%s", PG_PROC_DIR, t->name); + sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name); t->proc_ent = create_proc_entry(t->fname, 0600, NULL); if (!t->proc_ent) { printk("pktgen: cannot create %s procfs entry.\n", t->fname); @@ -3064,7 +3053,7 @@ static int __init pg_init(void) create_proc_dir(); - sprintf(module_fname, "net/%s/pgctrl", PG_PROC_DIR); + sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR); module_proc_ent = create_proc_entry(module_fname, 0600, NULL); if (!module_proc_ent) { printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname); diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 03a4734..6059e9e 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -230,7 +230,7 @@ static int __init ieee80211_init(void) struct proc_dir_entry *e; ieee80211_debug_level = debug; - ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net); + ieee80211_proc = proc_mkdir(DRV_NAME, proc_net); if (ieee80211_proc == NULL) { IEEE80211_ERROR("Unable to create " DRV_NAME " proc directory\n"); -- cgit v0.10.2 From 87e0f3dbd3693bc4583474ab191cbdd5e3d9d0fa Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 29 Sep 2005 00:05:58 +0100 Subject: [PATCH] n_r3964: drop bogus fmt casts - print pointers with %p - casting pointer structure field to int and printing it with %d... Signed-off-by: Alexey Dobriyan Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 2291a87..97d6dc2 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -229,8 +229,8 @@ static int __init r3964_init(void) TRACE_L("line discipline %d registered", N_R3964); TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, tty_ldisc_N_R3964.num); - TRACE_L("open=%x", (int)tty_ldisc_N_R3964.open); - TRACE_L("tty_ldisc_N_R3964 = %x", (int)&tty_ldisc_N_R3964); + TRACE_L("open=%p", tty_ldisc_N_R3964.open); + TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); } else { @@ -267,8 +267,8 @@ static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH spin_unlock_irqrestore(&pInfo->lock, flags); - TRACE_Q("add_tx_queue %x, length %d, tx_first = %x", - (int)pHeader, pHeader->length, (int)pInfo->tx_first ); + TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", + pHeader, pHeader->length, pInfo->tx_first ); } static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) @@ -285,10 +285,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) return; #ifdef DEBUG_QUEUE - printk("r3964: remove_from_tx_queue: %x, length %d - ", - (int)pHeader, (int)pHeader->length ); + printk("r3964: remove_from_tx_queue: %p, length %u - ", + pHeader, pHeader->length ); for(pDump=pHeader;pDump;pDump=pDump->next) - printk("%x ", (int)pDump); + printk("%p ", pDump); printk("\n"); #endif @@ -319,10 +319,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) spin_unlock_irqrestore(&pInfo->lock, flags); kfree(pHeader); - TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader); + TRACE_M("remove_from_tx_queue - kfree %p",pHeader); - TRACE_Q("remove_from_tx_queue: tx_first = %x, tx_last = %x", - (int)pInfo->tx_first, (int)pInfo->tx_last ); + TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", + pInfo->tx_first, pInfo->tx_last ); } static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) @@ -346,9 +346,9 @@ static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH spin_unlock_irqrestore(&pInfo->lock, flags); - TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d", - (int)pHeader, pHeader->length, - (int)pInfo->rx_first, pInfo->blocks_in_rx_queue); + TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", + pHeader, pHeader->length, + pInfo->rx_first, pInfo->blocks_in_rx_queue); } static void remove_from_rx_queue(struct r3964_info *pInfo, @@ -360,10 +360,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo, if(pHeader==NULL) return; - TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d", - (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue ); - TRACE_Q("remove_from_rx_queue: %x, length %d", - (int)pHeader, (int)pHeader->length ); + TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", + pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); + TRACE_Q("remove_from_rx_queue: %p, length %u", + pHeader, pHeader->length ); spin_lock_irqsave(&pInfo->lock, flags); @@ -401,10 +401,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo, spin_unlock_irqrestore(&pInfo->lock, flags); kfree(pHeader); - TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader); + TRACE_M("remove_from_rx_queue - kfree %p",pHeader); - TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d", - (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue ); + TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", + pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); } static void put_char(struct r3964_info *pInfo, unsigned char ch) @@ -506,8 +506,8 @@ static void transmit_block(struct r3964_info *pInfo) if(tty->driver->write_room) room=tty->driver->write_room(tty); - TRACE_PS("transmit_block %x, room %d, length %d", - (int)pBlock, room, pBlock->length); + TRACE_PS("transmit_block %p, room %d, length %d", + pBlock, room, pBlock->length); while(pInfo->tx_position < pBlock->length) { @@ -588,7 +588,7 @@ static void on_receive_block(struct r3964_info *pInfo) /* prepare struct r3964_block_header: */ pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL); - TRACE_M("on_receive_block - kmalloc %x",(int)pBlock); + TRACE_M("on_receive_block - kmalloc %p",pBlock); if(pBlock==NULL) return; @@ -868,11 +868,11 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg) if(pMsg) { kfree(pMsg); - TRACE_M("enable_signals - msg kfree %x",(int)pMsg); + TRACE_M("enable_signals - msg kfree %p",pMsg); } } kfree(pClient); - TRACE_M("enable_signals - kfree %x",(int)pClient); + TRACE_M("enable_signals - kfree %p",pClient); return 0; } } @@ -890,7 +890,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg) { /* add client to client list */ pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL); - TRACE_M("enable_signals - kmalloc %x",(int)pClient); + TRACE_M("enable_signals - kmalloc %p",pClient); if(pClient==NULL) return -ENOMEM; @@ -954,7 +954,7 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, queue_the_message: pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL); - TRACE_M("add_msg - kmalloc %x",(int)pMsg); + TRACE_M("add_msg - kmalloc %p",pMsg); if(pMsg==NULL) { return; } @@ -1067,11 +1067,11 @@ static int r3964_open(struct tty_struct *tty) struct r3964_info *pInfo; TRACE_L("open"); - TRACE_L("tty=%x, PID=%d, disc_data=%x", - (int)tty, current->pid, (int)tty->disc_data); + TRACE_L("tty=%p, PID=%d, disc_data=%p", + tty, current->pid, tty->disc_data); pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); - TRACE_M("r3964_open - info kmalloc %x",(int)pInfo); + TRACE_M("r3964_open - info kmalloc %p",pInfo); if(!pInfo) { @@ -1080,26 +1080,26 @@ static int r3964_open(struct tty_struct *tty) } pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - rx_buf kmalloc %x",(int)pInfo->rx_buf); + TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf); if(!pInfo->rx_buf) { printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); kfree(pInfo); - TRACE_M("r3964_open - info kfree %x",(int)pInfo); + TRACE_M("r3964_open - info kfree %p",pInfo); return -ENOMEM; } pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); - TRACE_M("r3964_open - tx_buf kmalloc %x",(int)pInfo->tx_buf); + TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf); if(!pInfo->tx_buf) { printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); kfree(pInfo->rx_buf); - TRACE_M("r3964_open - rx_buf kfree %x",(int)pInfo->rx_buf); + TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf); kfree(pInfo); - TRACE_M("r3964_open - info kfree %x",(int)pInfo); + TRACE_M("r3964_open - info kfree %p",pInfo); return -ENOMEM; } @@ -1154,11 +1154,11 @@ static void r3964_close(struct tty_struct *tty) if(pMsg) { kfree(pMsg); - TRACE_M("r3964_close - msg kfree %x",(int)pMsg); + TRACE_M("r3964_close - msg kfree %p",pMsg); } } kfree(pClient); - TRACE_M("r3964_close - client kfree %x",(int)pClient); + TRACE_M("r3964_close - client kfree %p",pClient); pClient=pNext; } /* Remove jobs from tx_queue: */ @@ -1177,11 +1177,11 @@ static void r3964_close(struct tty_struct *tty) /* Free buffers: */ wake_up_interruptible(&pInfo->read_wait); kfree(pInfo->rx_buf); - TRACE_M("r3964_close - rx_buf kfree %x",(int)pInfo->rx_buf); + TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf); kfree(pInfo->tx_buf); - TRACE_M("r3964_close - tx_buf kfree %x",(int)pInfo->tx_buf); + TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf); kfree(pInfo); - TRACE_M("r3964_close - info kfree %x",(int)pInfo); + TRACE_M("r3964_close - info kfree %p",pInfo); } static ssize_t r3964_read(struct tty_struct *tty, struct file *file, @@ -1234,7 +1234,7 @@ repeat: count = sizeof(struct r3964_client_message); kfree(pMsg); - TRACE_M("r3964_read - msg kfree %x",(int)pMsg); + TRACE_M("r3964_read - msg kfree %p",pMsg); if (copy_to_user(buf,&theMsg, count)) return -EFAULT; @@ -1279,7 +1279,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, * Allocate a buffer for the data and copy it from the buffer with header prepended */ new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); - TRACE_M("r3964_write - kmalloc %x",(int)new_data); + TRACE_M("r3964_write - kmalloc %p",new_data); if (new_data == NULL) { if (pInfo->flags & R3964_DEBUG) { -- cgit v0.10.2 From 775b048d09c85d87a65a7ccd9c4f9372953a5d95 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:07:29 +0100 Subject: [PATCH] cyblafb: portability fixes, sanitized work with pointers Signed-off-by: Al Viro Acked-by: Knut Petersen Signed-off-by: Linus Torvalds diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index ae2762c..6992100 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -410,20 +410,21 @@ static void cyblafb_imageblit(struct fb_info *info, out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); while(index < index_end) { + const char *p = image->data + index; for(i=0;idata + index))); + out32(GE9C,*(u32*)p); + p+=4; index+=4; } switch(width_dbs) { case 0: break; - case 8: out32(GE9C,*((u8*)((u32)image->data+index))); + case 8: out32(GE9C,*(u8*)p); index+=1; break; - case 16: out32(GE9C,*((u16*)((u32)image->data+index))); + case 16: out32(GE9C,*(u16*)p); index+=2; break; - case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) | - (u32)(*((u8*)((u32)image->data+index+2)))<<16); + case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16); index+=3; break; } -- cgit v0.10.2 From 2ad4f86b60b649fd7428265c08d73a3bd360c81b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:09:02 +0100 Subject: [PATCH] arm/versatile iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 3c8862f..58c1330 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -52,8 +52,9 @@ * * Setup a VA for the Versatile Vectored Interrupt Controller. */ -#define VA_VIC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) -#define VA_SIC_BASE IO_ADDRESS(VERSATILE_SIC_BASE) +#define __io_address(n) __io(IO_ADDRESS(n)) +#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) +#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) static void vic_mask_irq(unsigned int irq) { @@ -214,7 +215,7 @@ void __init versatile_map_io(void) iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc)); } -#define VERSATILE_REFCOUNTER (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) +#define VERSATILE_REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) /* * This is the Versatile sched_clock implementation. This has @@ -231,7 +232,7 @@ unsigned long long sched_clock(void) } -#define VERSATILE_FLASHCTRL (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET) +#define VERSATILE_FLASHCTRL (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET) static int versatile_flash_init(void) { @@ -309,7 +310,7 @@ static struct platform_device smc91x_device = { .resource = smc91x_resources, }; -#define VERSATILE_SYSMCI (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) +#define VERSATILE_SYSMCI (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET) unsigned int mmc_status(struct device *dev) { @@ -343,11 +344,11 @@ static const struct icst307_params versatile_oscvco_params = { static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) { - unsigned long sys_lock = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; + void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; #if defined(CONFIG_ARCH_VERSATILE_PB) - unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET; + void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET; #elif defined(CONFIG_MACH_VERSATILE_AB) - unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET; + void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET; #endif u32 val; @@ -483,7 +484,7 @@ static struct clcd_panel epson_2_2_in = { */ static struct clcd_panel *versatile_clcd_panel(void) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; struct clcd_panel *panel = &vga; u32 val; @@ -510,7 +511,7 @@ static struct clcd_panel *versatile_clcd_panel(void) */ static void versatile_clcd_disable(struct clcd_fb *fb) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); @@ -522,7 +523,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb) * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off */ if (fb->panel == &sanyo_2_5_in) { - unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL); + void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); unsigned long ctrl; ctrl = readl(versatile_ib2_ctrl); @@ -537,7 +538,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb) */ static void versatile_clcd_enable(struct clcd_fb *fb) { - unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; + void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET; u32 val; val = readl(sys_clcd); @@ -571,7 +572,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb) * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on */ if (fb->panel == &sanyo_2_5_in) { - unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL); + void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL); unsigned long ctrl; ctrl = readl(versatile_ib2_ctrl); @@ -720,7 +721,7 @@ static struct amba_device *amba_devs[] __initdata = { }; #ifdef CONFIG_LEDS -#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) +#define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) static void versatile_leds_event(led_event_t ledevt) { @@ -778,11 +779,11 @@ void __init versatile_init(void) /* * Where is the timer (VA)? */ -#define TIMER0_VA_BASE IO_ADDRESS(VERSATILE_TIMER0_1_BASE) -#define TIMER1_VA_BASE (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20) -#define TIMER2_VA_BASE IO_ADDRESS(VERSATILE_TIMER2_3_BASE) -#define TIMER3_VA_BASE (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20) -#define VA_IC_BASE IO_ADDRESS(VERSATILE_VIC_BASE) +#define TIMER0_VA_BASE __io_address(VERSATILE_TIMER0_1_BASE) +#define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20) +#define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE) +#define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20) +#define VA_IC_BASE __io_address(VERSATILE_VIC_BASE) /* * How long is the timer interval? @@ -877,12 +878,12 @@ static void __init versatile_timer_init(void) * VERSATILE_REFCLK is 32KHz * VERSATILE_TIMCLK is 1MHz */ - val = readl(IO_ADDRESS(VERSATILE_SCTL_BASE)); + val = readl(__io_address(VERSATILE_SCTL_BASE)); writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, - IO_ADDRESS(VERSATILE_SCTL_BASE)); + __io_address(VERSATILE_SCTL_BASE)); /* * Initialise to a known state (all timers off) diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h index 9f895bf..47e904c 100644 --- a/include/asm-arm/arch-versatile/io.h +++ b/include/asm-arm/arch-versatile/io.h @@ -22,7 +22,11 @@ #define IO_SPACE_LIMIT 0xffffffff -#define __io(a) ((void __iomem *)(a)) +static inline void __iomem *__io(unsigned long addr) +{ + return (void __iomem *)addr; +} +#define __io(a) __io(a) #define __mem_pci(a) (a) #define __mem_isa(a) (a) -- cgit v0.10.2 From 272cd2b71d478371e0a5bf2c76a1e50cbf178698 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:10:01 +0100 Subject: [PATCH] arm/rpc iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h index be9754a..9d7f873 100644 --- a/include/asm-arm/arch-rpc/hardware.h +++ b/include/asm-arm/arch-rpc/hardware.h @@ -15,7 +15,7 @@ #include #ifndef __ASSEMBLY__ -#define IOMEM(x) ((void __iomem *)(x)) +#define IOMEM(x) ((void __iomem *)(unsigned long)(x)) #else #define IOMEM(x) x #endif /* __ASSEMBLY__ */ @@ -52,7 +52,7 @@ /* * IO Addresses */ -#define VIDC_BASE (void __iomem *)0xe0400000 +#define VIDC_BASE IOMEM(0xe0400000) #define EXPMASK_BASE 0xe0360000 #define IOMD_BASE IOMEM(0xe0200000) #define IOC_BASE IOMEM(0xe0200000) -- cgit v0.10.2 From 0cc13a5442901835192ba47427f0f4e4d525d935 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:12:13 +0100 Subject: [PATCH] ia64 basic __user annotations - document places where we pass kernel address to low-level primitive that deals with kernel/user addresses - uintptr_t is unsigned long, not long Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h index 3a7829b..9adb512 100644 --- a/include/asm-ia64/uaccess.h +++ b/include/asm-ia64/uaccess.h @@ -187,8 +187,8 @@ extern void __get_user_unknown (void); ({ \ const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ __typeof__ (size) __gu_size = (size); \ - long __gu_err = -EFAULT, __gu_val = 0; \ - \ + long __gu_err = -EFAULT; \ + unsigned long __gu_val = 0; \ if (!check || __access_ok(__gu_ptr, size, segment)) \ switch (__gu_size) { \ case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break; \ @@ -240,13 +240,13 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use static inline unsigned long __copy_to_user (void __user *to, const void *from, unsigned long count) { - return __copy_user(to, (void __user *) from, count); + return __copy_user(to, (__force void __user *) from, count); } static inline unsigned long __copy_from_user (void *to, const void __user *from, unsigned long count) { - return __copy_user((void __user *) to, from, count); + return __copy_user((__force void __user *) to, from, count); } #define __copy_to_user_inatomic __copy_to_user @@ -258,7 +258,7 @@ __copy_from_user (void *to, const void __user *from, unsigned long count) long __cu_len = (n); \ \ if (__access_ok(__cu_to, __cu_len, get_fs())) \ - __cu_len = __copy_user(__cu_to, (void __user *) __cu_from, __cu_len); \ + __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \ __cu_len; \ }) @@ -270,7 +270,7 @@ __copy_from_user (void *to, const void __user *from, unsigned long count) \ __chk_user_ptr(__cu_from); \ if (__access_ok(__cu_from, __cu_len, get_fs())) \ - __cu_len = __copy_user((void __user *) __cu_to, __cu_from, __cu_len); \ + __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \ __cu_len; \ }) -- cgit v0.10.2 From c28144763a7dcdceb2c16a5ac9c8e0022d547d28 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:16:02 +0100 Subject: [PATCH] s390 signal annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 7358cdb..4ff6808 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -143,7 +143,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) break; case __SI_FAULT >> 16: err |= __get_user(tmp, &from->si_addr); - to->si_addr = (void *)(u64) (tmp & PSW32_ADDR_INSN); + to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN); break; case __SI_POLL >> 16: err |= __get_user(to->si_band, &from->si_band); @@ -338,7 +338,7 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) return -EFAULT; - kss.ss_sp = (void *) ss_sp; + kss.ss_sp = (void __user *) ss_sp; } set_fs (KERNEL_DS); @@ -461,7 +461,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) goto badframe; err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); - st.ss_sp = (void *) A((unsigned long)ss_sp); + st.ss_sp = compat_ptr(ss_sp); err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size); err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags); if (err) diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6a3f5b7..6e0110d 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -376,8 +376,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(NULL, &frame->uc.uc_link); + err |= __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gprs[15]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); diff --git a/include/asm-s390/sigcontext.h b/include/asm-s390/sigcontext.h index d57bc0c..8035453 100644 --- a/include/asm-s390/sigcontext.h +++ b/include/asm-s390/sigcontext.h @@ -61,7 +61,7 @@ typedef struct struct sigcontext { unsigned long oldmask[_SIGCONTEXT_NSIG_WORDS]; - _sigregs *sregs; + _sigregs __user *sregs; }; diff --git a/include/asm-s390/signal.h b/include/asm-s390/signal.h index 3d6e11c..7084626 100644 --- a/include/asm-s390/signal.h +++ b/include/asm-s390/signal.h @@ -165,7 +165,7 @@ struct sigaction { #endif /* __KERNEL__ */ typedef struct sigaltstack { - void *ss_sp; + void __user *ss_sp; int ss_flags; size_t ss_size; } stack_t; -- cgit v0.10.2 From ea8a918eb71b503be13b861dbe18b93932fd6b62 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:17:49 +0100 Subject: [PATCH] ppc64 get_user annotations long is not uintptr_t, unsigned long is. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h index c181a60d..132c127 100644 --- a/include/asm-ppc64/uaccess.h +++ b/include/asm-ppc64/uaccess.h @@ -164,7 +164,8 @@ do { \ #define __get_user_nocheck(x,ptr,size) \ ({ \ - long __gu_err, __gu_val; \ + long __gu_err; \ + unsigned long __gu_val; \ might_sleep(); \ __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ @@ -173,7 +174,8 @@ do { \ #define __get_user_check(x,ptr,size) \ ({ \ - long __gu_err = -EFAULT, __gu_val = 0; \ + long __gu_err = -EFAULT; \ + unsigned long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ might_sleep(); \ if (access_ok(VERIFY_READ,__gu_addr,size)) \ -- cgit v0.10.2 From 9fcdfcd90526c8c5c2bd117fd3713f8f0f1a46a8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:31:14 +0100 Subject: [PATCH] ppc32 ld.script fix for building on ppc64 In arch/ppc/boot/ld.script we need OUTPUT_ARCH(powerpc:common) for the same reasons why we need it in vmlinux.lds.S; when we build on ppc64 box, we need to be explicit about the target. See http://linus.bkbits.net:8080/linux-2.5/cset@1.1784.8.10 for the corresponding fix in vmlinux.lds.S. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/ppc/boot/ld.script b/arch/ppc/boot/ld.script index 9362193..d4dd8f1 100644 --- a/arch/ppc/boot/ld.script +++ b/arch/ppc/boot/ld.script @@ -1,4 +1,4 @@ -OUTPUT_ARCH(powerpc) +OUTPUT_ARCH(powerpc:common) SECTIONS { /* Read-only sections, merged into text segment: */ -- cgit v0.10.2 From a7625d6e49cb4fd94be7576d85422c33003101b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:34:30 +0100 Subject: [PATCH] mv64x60 iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 839f887..4849850 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -34,7 +34,7 @@ u8 mv64x60_pci_exclude_bridge = 1; DEFINE_SPINLOCK(mv64x60_lock); static phys_addr_t mv64x60_bridge_pbase; -static void *mv64x60_bridge_vbase; +static void __iomem *mv64x60_bridge_vbase; static u32 mv64x60_bridge_type = MV64x60_TYPE_INVALID; static u32 mv64x60_bridge_rev; #if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260) @@ -938,7 +938,7 @@ mv64x60_setup_for_chip(struct mv64x60_handle *bh) * * Return the virtual address of the bridge's registers. */ -void * +void __iomem * mv64x60_get_bridge_vbase(void) { return mv64x60_bridge_vbase; diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h index 75c2ffa..ee2f918 100644 --- a/include/asm-ppc/mv64x60.h +++ b/include/asm-ppc/mv64x60.h @@ -233,7 +233,7 @@ struct mv64x60_chip_info { struct mv64x60_handle { u32 type; /* type of bridge */ u32 rev; /* revision of bridge */ - void *v_base; /* virtual base addr of bridge regs */ + void __iomem *v_base;/* virtual base addr of bridge regs */ phys_addr_t p_base; /* physical base addr of bridge regs */ u32 pci_mode_a; /* pci 0 mode: conventional pci, pci-x*/ @@ -303,7 +303,7 @@ void mv64x60_alloc_hose(struct mv64x60_handle *bh, u32 cfg_addr, u32 cfg_data, struct pci_controller **hose); int mv64x60_get_type(struct mv64x60_handle *bh); int mv64x60_setup_for_chip(struct mv64x60_handle *bh); -void *mv64x60_get_bridge_vbase(void); +void __iomem *mv64x60_get_bridge_vbase(void); u32 mv64x60_get_bridge_type(void); u32 mv64x60_get_bridge_rev(void); void mv64x60_get_mem_windows(struct mv64x60_handle *bh, -- cgit v0.10.2 From be88ec74cb48d1f60d0c0f059843f846f4481d87 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:36:10 +0100 Subject: [PATCH] i810-i2c iomem annotations Signed-off-by: Al Viro Acked-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index fda53aa..689d258 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c @@ -44,7 +44,7 @@ static void i810i2c_setscl(void *data, int state) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); @@ -55,7 +55,7 @@ static void i810i2c_setsda(void *data, int state) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); @@ -66,7 +66,7 @@ static int i810i2c_getscl(void *data) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOB, SCL_DIR_MASK); i810_writel(mmio, GPIOB, 0); @@ -77,7 +77,7 @@ static int i810i2c_getsda(void *data) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOB, SDA_DIR_MASK); i810_writel(mmio, GPIOB, 0); @@ -88,7 +88,7 @@ static void i810ddc_setscl(void *data, int state) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); @@ -99,7 +99,7 @@ static void i810ddc_setsda(void *data, int state) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); @@ -110,7 +110,7 @@ static int i810ddc_getscl(void *data) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOA, SCL_DIR_MASK); i810_writel(mmio, GPIOA, 0); @@ -121,7 +121,7 @@ static int i810ddc_getsda(void *data) { struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data; struct i810fb_par *par = chan->par; - u8 *mmio = par->mmio_start_virtual; + u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(mmio, GPIOA, SDA_DIR_MASK); i810_writel(mmio, GPIOA, 0); -- cgit v0.10.2 From ae8aed0314064da3002879fedc2d262c72865a17 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:37:34 +0100 Subject: [PATCH] saa6588 __user annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/rds.h b/drivers/media/video/rds.h index 30337d0..0d30eb7 100644 --- a/drivers/media/video/rds.h +++ b/drivers/media/video/rds.h @@ -31,7 +31,7 @@ struct rds_command { unsigned int block_count; int result; - unsigned char *buffer; + unsigned char __user *buffer; struct file *instance; poll_table *event_list; }; diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 1a657a7..72b70eb 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -157,7 +157,7 @@ static struct i2c_client client_template; /* ---------------------------------------------------------------------- */ -static int block_to_user_buf(struct saa6588 *s, unsigned char *user_buf) +static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf) { int i; @@ -191,7 +191,7 @@ static void read_from_buf(struct saa6588 *s, struct rds_command *a) { unsigned long flags; - unsigned char *buf_ptr = a->buffer; /* This is a user space buffer! */ + unsigned char __user *buf_ptr = a->buffer; unsigned int i; unsigned int rd_blocks; -- cgit v0.10.2 From b2846dfa4aa1bbbf3f9977d67566952d7f621009 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 00:42:27 +0100 Subject: [PATCH] mv64x60_wdt __user annotations and cleanups - use nonseekable_open() instead of messing with if (*ppos != file->f_pos) return -EISPIPE in ->write() (->read is NULL). - trivial __user annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c index 1436aea..6d3ff08 100644 --- a/drivers/char/watchdog/mv64x60_wdt.c +++ b/drivers/char/watchdog/mv64x60_wdt.c @@ -87,6 +87,8 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file) mv64x60_wdt_service(); mv64x60_wdt_handler_enable(); + nonseekable_open(inode, file); + return 0; } @@ -103,12 +105,9 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) return 0; } -static ssize_t mv64x60_wdt_write(struct file *file, const char *data, +static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { - if (*ppos != file->f_pos) - return -ESPIPE; - if (len) mv64x60_wdt_service(); @@ -119,6 +118,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int timeout; + void __user *argp = (void __user *)arg; static struct watchdog_info info = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 0, @@ -127,13 +127,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - if (put_user(wdt_status, (int *)arg)) + if (put_user(wdt_status, (int __user *)argp)) return -EFAULT; wdt_status &= ~WDIOF_KEEPALIVEPING; break; @@ -154,7 +154,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, case WDIOC_GETTIMEOUT: timeout = mv64x60_wdt_timeout * HZ; - if (put_user(timeout, (int *)arg)) + if (put_user(timeout, (int __user *)argp)) return -EFAULT; break; -- cgit v0.10.2 From 375726d7ed08bd8cf2fe3cfe6b164ffb37fa7e90 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Thu, 29 Sep 2005 05:19:51 +0800 Subject: [PATCH] intelfb: Fix regression (blank display) from ioremap patch - Workaround for the ioremap patch that produces a blank display on some chipsets - Make hwcursor = 0 the default. The hardware cursor does not work with all hardware. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 773ae11..1cd942a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -768,6 +768,7 @@ config FB_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_SOFT_CURSOR help This driver supports the on-board graphics built in to the Intel 830M/845G/852GM/855GM/865G chipsets. diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index bf62e6e..80a0934 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -226,7 +226,7 @@ MODULE_DEVICE_TABLE(pci, intelfb_pci_table); static int accel = 1; static int vram = 4; -static int hwcursor = 1; +static int hwcursor = 0; static int mtrr = 1; static int fixed = 0; static int noinit = 0; @@ -609,15 +609,9 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) dinfo->accel = 0; } - if (MB(voffset) < stolen_size) - offset = (stolen_size >> 12); - else - offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; - /* Framebuffer parameters - Use all the stolen memory if >= vram */ - if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) + MB(vram))) { + if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) { dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size); - dinfo->fb.offset = 0; dinfo->fbmem_gart = 0; } else { dinfo->fb.size = MB(vram); @@ -648,6 +642,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (MB(voffset) < stolen_size) + offset = (stolen_size >> 12); + else + offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; + /* set the mem offsets - set them after the already used pages */ if (dinfo->accel) { dinfo->ring.offset = offset + gtt_info.current_memory; @@ -662,10 +661,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->cursor.size >> 12); } + /* Allocate memories (which aren't stolen) */ /* Map the fb and MMIO regions */ /* ioremap only up to the end of used aperture */ dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache - (dinfo->aperture.physical, (dinfo->fb.offset << 12) + (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12) + dinfo->fb.size); if (!dinfo->aperture.virtual) { ERR_MSG("Cannot remap FB region.\n"); @@ -682,7 +682,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - /* Allocate memories (which aren't stolen) */ if (dinfo->accel) { if (!(dinfo->gtt_ring_mem = agp_allocate_memory(bridge, dinfo->ring.size >> 12, @@ -1484,7 +1483,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #endif if (!dinfo->hwcursor) - return -ENXIO; + return soft_cursor(info, cursor); intelfbhw_cursor_hide(dinfo); -- cgit v0.10.2 From fe984bba30a29398578da3d8c0503fa39e84b838 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 29 Sep 2005 05:24:38 +0800 Subject: [PATCH] s3c2410fb: Minor warning fix The function s3c2410fb_activate_var does not return a value, therefore it should be declared void. Signed-off-by: Ben Dooks Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 00c0223..5ab79af 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -228,8 +228,8 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, * information */ -static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi, - struct fb_var_screeninfo *var) +static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, + struct fb_var_screeninfo *var) { fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; -- cgit v0.10.2 From 82810a906f8734ae6503ea11436a7164d2f86f2e Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Wed, 28 Sep 2005 16:42:54 -0700 Subject: [PATCH] Fix ixp4xx MTD driver module build Missing ';' breaks module build. Signed-off-by: Deepak Saxena Signed-off-by: Linus Torvalds diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 5afe660..bbb0e6e 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -254,6 +254,6 @@ module_init(ixp4xx_flash_init); module_exit(ixp4xx_flash_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems") +MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); MODULE_AUTHOR("Deepak Saxena"); -- cgit v0.10.2 From b38708fca9cc60d8a073a67c3b366116e38011c5 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Wed, 28 Sep 2005 18:07:01 -0700 Subject: [PATCH] Fix thinko in previous ARM 2917/1 patch Previous patch accidently add IXDP425 mach entry when IXDP465 is configured. Signed-off-by: Deepak Saxena Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 39b06ed..0a41080 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -123,7 +123,7 @@ static void __init ixdp425_init(void) platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); } -#ifdef CONFIG_ARCH_IXDP465 +#ifdef CONFIG_ARCH_IXDP425 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") /* Maintainer: MontaVista Software, Inc. */ .phys_ram = PHYS_OFFSET, -- cgit v0.10.2 From aa55a08687059aa169d10a313c41f238c2070488 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 29 Sep 2005 19:58:53 +0400 Subject: [PATCH] fix TASK_STOPPED vs TASK_NONINTERACTIVE interaction do_signal_stop: for_each_thread(t) { if (t->state < TASK_STOPPED) ++sig->group_stop_count; } However, TASK_NONINTERACTIVE > TASK_STOPPED, so this loop will not count TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE threads. See also wait_task_stopped(), which checks ->state > TASK_STOPPED. Signed-off-by: Oleg Nesterov [ We really probably should always use the appropriate bitmasks to test task states, not do it like this. Using something like #define TASK_RUNNABLE (TASK_RUNNING | TASK_INTERRUPTIBLE | \ TASK_UNINTERRUPTIBLE | TASK_NONINTERACTIVE) and then doing "if (task->state & TASK_RUNNABLE)" or similar. But the ordering of the task states is historical, and keeping the ordering does make sense regardless. ] Signed-off-by: Linus Torvalds diff --git a/include/linux/sched.h b/include/linux/sched.h index 49e617f..afe6c61 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -110,11 +110,11 @@ extern unsigned long nr_iowait(void); #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 -#define TASK_STOPPED 4 -#define TASK_TRACED 8 -#define EXIT_ZOMBIE 16 -#define EXIT_DEAD 32 -#define TASK_NONINTERACTIVE 64 +#define TASK_NONINTERACTIVE 4 +#define TASK_STOPPED 8 +#define TASK_TRACED 16 +#define EXIT_ZOMBIE 32 +#define EXIT_DEAD 64 #define __set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) -- cgit v0.10.2 From 4a8342d233a39ee582e9f7260e12d2f5fd194a05 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 29 Sep 2005 15:18:21 -0700 Subject: Revert task flag re-ordering, add comments Roland points out that the flags end up having non-obvious dependencies elsewhere, so revert aa55a08687059aa169d10a313c41f238c2070488 and add some comments about why things are as they are. We'll just have to fix up the broken comparisons. Roland has a patch. Signed-off-by: Linus Torvalds diff --git a/include/linux/sched.h b/include/linux/sched.h index afe6c61..c3ba31f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -107,14 +107,26 @@ extern unsigned long nr_iowait(void); #include +/* + * Task state bitmask. NOTE! These bits are also + * encoded in fs/proc/array.c: get_task_state(). + * + * We have two separate sets of flags: task->state + * is about runnability, while task->exit_state are + * about the task exiting. Confusing, but this way + * modifying one set can't modify the other one by + * mistake. + */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 -#define TASK_NONINTERACTIVE 4 -#define TASK_STOPPED 8 -#define TASK_TRACED 16 -#define EXIT_ZOMBIE 32 -#define EXIT_DEAD 64 +#define TASK_STOPPED 4 +#define TASK_TRACED 8 +/* in tsk->exit_state */ +#define EXIT_ZOMBIE 16 +#define EXIT_DEAD 32 +/* in tsk->state again */ +#define TASK_NONINTERACTIVE 64 #define __set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) -- cgit v0.10.2 From 5acbc5cb507e6c381b70093b1081854708e82b16 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 29 Sep 2005 14:54:42 -0700 Subject: [PATCH] Fix task state testing properly in do_signal_stop() Any tests using < TASK_STOPPED or the like are left over from the time when the TASK_ZOMBIE and TASK_DEAD bits were in the same word, and it served to check for "stopped or dead". I think this one in do_signal_stop is the only such case. It has been buggy ever since exit_state was separated, and isn't testing the exit_state value. Signed-off-by: Roland McGrath Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index 5a27470..619b027 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1763,7 +1763,8 @@ do_signal_stop(int signr) * stop is always done with the siglock held, * so this check has no races. */ - if (t->state < TASK_STOPPED) { + if (!t->exit_state && + !(t->state & (TASK_STOPPED|TASK_TRACED))) { stop_count++; signal_wake_up(t, 0); } -- cgit v0.10.2 From 7d318d774789657c37a5e994a4a2cf59d4879ae7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 29 Sep 2005 22:05:55 +0200 Subject: [PATCH] Fix up TLB flush filter disabling I checked with AMD and they requested to only disable it for family 15. Also disable it for i386 too. And some style fixes. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 73aeaf5..4c1ddf2b 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -28,6 +28,22 @@ static void __init init_amd(struct cpuinfo_x86 *c) int mbytes = num_physpages >> (20-PAGE_SHIFT); int r; +#ifdef CONFIG_SMP + unsigned long value; + + /* Disable TLB flush filter by setting HWCR.FFDIS on K8 + * bit 6 of msr C001_0015 + * + * Errata 63 for SH-B3 steppings + * Errata 122 for all steppings (F+ have it disabled by default) + */ + if (c->x86 == 15) { + rdmsrl(MSR_K7_HWCR, value); + value |= 1 << 6; + wrmsrl(MSR_K7_HWCR, value); + } +#endif + /* * FIXME: We should handle the K5 here. Set up the write * range and also turn on MSR 83 bits 4 and 31 (write alloc, diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 238f73e..257f5ba 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -831,8 +831,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) #endif } -#define HWCR 0xc0010015 - static int __init init_amd(struct cpuinfo_x86 *c) { int r; @@ -841,14 +839,18 @@ static int __init init_amd(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP unsigned long value; - // Disable TLB flush filter by setting HWCR.FFDIS: - // bit 6 of msr C001_0015 - // - // Errata 63 for SH-B3 steppings - // Errata 122 for all(?) steppings - rdmsrl(HWCR, value); - value |= 1 << 6; - wrmsrl(HWCR, value); + /* + * Disable TLB flush filter by setting HWCR.FFDIS on K8 + * bit 6 of msr C001_0015 + * + * Errata 63 for SH-B3 steppings + * Errata 122 for all steppings (F+ have it disabled by default) + */ + if (c->x86 == 15) { + rdmsrl(MSR_K8_HWCR, value); + value |= 1 << 6; + wrmsrl(MSR_K8_HWCR, value); + } #endif /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h index 4d727f3..5a7fe3c 100644 --- a/include/asm-x86_64/msr.h +++ b/include/asm-x86_64/msr.h @@ -234,6 +234,7 @@ static inline unsigned int cpuid_edx(unsigned int op) #define MSR_K8_TOP_MEM1 0xC001001A #define MSR_K8_TOP_MEM2 0xC001001D #define MSR_K8_SYSCFG 0xC0010010 +#define MSR_K8_HWCR 0xC0010015 /* K6 MSRs */ #define MSR_K6_EFER 0xC0000080 -- cgit v0.10.2 From 7644143cd6f7e029f3a8ea64f5fb0ab33ec39f72 Mon Sep 17 00:00:00 2001 From: Mike Waychison Date: Fri, 30 Sep 2005 00:01:27 +0200 Subject: [PATCH] x86_64: Fix mce_log The attempt to fixup the lockless mce log buffer introduced an infinite loop when trying to find a free entry. And: Using rcu_dereference() to load mcelog.next doesn't seem to be sufficient enough to ensure that mcelog.next is loaded each time around the loop in mce_log(). Instead, use an explicit rmb() to ensure that the compiler gets it right. AK: turned the smp_wmbs into true wmbs to make sure they are not reordered by the compiler on UP. Signed-off-by: Mike Waychison Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 08203b0..69541db 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -54,9 +54,12 @@ void mce_log(struct mce *mce) { unsigned next, entry; mce->finished = 0; - smp_wmb(); + wmb(); for (;;) { entry = rcu_dereference(mcelog.next); + /* The rmb forces the compiler to reload next in each + iteration */ + rmb(); for (;;) { /* When the buffer fills up discard new entries. Assume that the earlier errors are the more interesting. */ @@ -69,6 +72,7 @@ void mce_log(struct mce *mce) entry++; continue; } + break; } smp_rmb(); next = entry + 1; @@ -76,9 +80,9 @@ void mce_log(struct mce *mce) break; } memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); - smp_wmb(); + wmb(); mcelog.entry[entry].finished = 1; - smp_wmb(); + wmb(); if (!test_and_set_bit(0, &console_logged)) notify_user = 1; -- cgit v0.10.2 From 411b67b4b6a4dd1e0292a6a58dd753978179d173 Mon Sep 17 00:00:00 2001 From: Kostik Belousov Date: Wed, 28 Sep 2005 18:21:28 +0300 Subject: [PATCH] readv/writev syscalls are not checked by lsm it seems that readv(2)/writev(2) syscalls do not call file_permission callback. Looks like this is overlook. I have filled the issue into redhat bugzilla as https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=169433 and got the recommendation to post this on lsm mailing list. The following trivial patch solves the problem. Signed-off-by: Kostik Belousov Signed-off-by: Chris Wright diff --git a/fs/read_write.c b/fs/read_write.c index b60324a..a091ee4 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -499,6 +499,9 @@ static ssize_t do_readv_writev(int type, struct file *file, ret = rw_verify_area(type, file, pos, tot_len); if (ret) goto out; + ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); + if (ret) + goto out; fnv = NULL; if (type == READ) { -- cgit v0.10.2 From a44fe13eab664ac488ced0845d9885b019bd24c5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 30 Sep 2005 08:25:17 +1000 Subject: [PATCH] Fix ppc64 smu driver locking The SMU driver has a small mistake in the locking of the interrupt code, if polled access and interrupt access race, interrupt may take a lock and return without releasing it. This fixes it. With that patch, the driver is rock solid with my experimental thermal control (which bangs it pretty hard) racing with real time clock and cpufreq handling. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a85ac18..9b38674 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -153,8 +153,10 @@ static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs) spin_lock_irqsave(&smu->lock, flags); gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell); - if ((gpio & 7) != 7) + if ((gpio & 7) != 7) { + spin_unlock_irqrestore(&smu->lock, flags); return IRQ_HANDLED; + } cmd = smu->cmd_cur; smu->cmd_cur = NULL; -- cgit v0.10.2 From dce79affd5d04e9cbabe35016eda55213b9b36f6 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Fri, 30 Sep 2005 00:17:35 +0100 Subject: [ARM] 2941/1: Fix running legacy binaries from a soft-float root filesystem with CONFIG_IWMMXT. Patch from Daniel Jacobowitz Thread flags are inherited on fork(). In order for a binary which has the iWMMXt coprocessor enabled to run a binary which needs the FPA emulation, we need to explicitly clear TIF_USING_IWMMXT if we are not going to set it. Signed-off-by: Daniel Jacobowitz Signed-off-by: Russell King diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index a1696ba..7da97a9 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -124,6 +124,8 @@ do { \ if (((ex).e_flags & EF_ARM_EABI_MASK) || \ ((ex).e_flags & EF_ARM_SOFT_FLOAT)) \ set_thread_flag(TIF_USING_IWMMXT); \ + else \ + clear_thread_flag(TIF_USING_IWMMXT); \ } while (0) #endif -- cgit v0.10.2 From 01ff367e62f0474e4d39aa5812cbe2a30d96e1e9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Sep 2005 17:07:20 -0700 Subject: [TCP]: Revert 6b251858d377196b8cea20e65cae60f584a42735 But retain the comment fix. Alexey Kuznetsov has explained the situation as follows: -------------------- I think the fix is incorrect. Look, the RFC function init_cwnd(mss) is not continuous: f.e. for mss=1095 it needs initial window 1095*4, but for mss=1096 it is 1096*3. We do not know exactly what mss sender used for calculations. If we advertised 1096 (and calculate initial window 3*1096), the sender could limit it to some value < 1096 and then it will need window his_mss*4 > 3*1096 to send initial burst. See? So, the honest function for inital rcv_wnd derived from tcp_init_cwnd() is: init_rcv_wnd(mss)= min { init_cwnd(mss1)*mss1 for mss1 <= mss } It is something sort of: if (mss < 1096) return mss*4; if (mss < 1096*2) return 1096*4; return mss*2; (I just scrablled a graph of piece of paper, it is difficult to see or to explain without this) I selected it differently giving more window than it is strictly required. Initial receive window must be large enough to allow sender following to the rfc (or just setting initial cwnd to 2) to send initial burst. But besides that it is arbitrary, so I decided to give slack space of one segment. Actually, the logic was: If mss is low/normal (<=ethernet), set window to receive more than initial burst allowed by rfc under the worst conditions i.e. mss*4. This gives slack space of 1 segment for ethernet frames. For msses slighlty more than ethernet frame, take 3. Try to give slack space of 1 frame again. If mss is huge, force 2*mss. No slack space. Value 1460*3 is really confusing. Minimal one is 1096*2, but besides that it is an arbitrary value. It was meant to be ~4096. 1460*3 is just the magic number from RFC, 1460*3 = 1095*4 is the magic :-), so that I guess hands typed this themselves. -------------------- Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index caf2e2c..c5b911f 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -194,12 +194,11 @@ void tcp_select_initial_window(int __space, __u32 mss, * will be satisfied with 2. */ if (mss > (1<<*rcv_wscale)) { - int init_cwnd; - - if (mss > 1460) + int init_cwnd = 4; + if (mss > 1460*3) init_cwnd = 2; - else - init_cwnd = (mss > 1095) ? 3 : 4; + else if (mss > 1460) + init_cwnd = 3; if (*rcv_wnd > init_cwnd*mss) *rcv_wnd = init_cwnd*mss; } -- cgit v0.10.2 From 09e9ec87111ba818d8171262b15ba4c357eb1d27 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 29 Sep 2005 17:17:15 -0700 Subject: [TCP]: Don't over-clamp window in tcp_clamp_window() From: Alexey Kuznetsov Handle better the case where the sender sends full sized frames initially, then moves to a mode where it trickles out small amounts of data at a time. This known problem is even mentioned in the comments above tcp_grow_window() in tcp_input.c, specifically: ... * The scheme does not work when sender sends good segments opening * window and then starts to feed us spagetti. But it should work * in common situations. Otherwise, we have to rely on queue collapsing. ... When the sender gives full sized frames, the "struct sk_buff" overhead from each packet is small. So we'll advertize a larger window. If the sender moves to a mode where small segments are sent, this ratio becomes tilted to the other extreme and we start overrunning the socket buffer space. tcp_clamp_window() tries to address this, but it's clamping of tp->window_clamp is a wee bit too aggressive for this particular case. Fix confirmed by Ion Badulescu. Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a7537c7..677419d0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -355,8 +355,6 @@ static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp) app_win -= icsk->icsk_ack.rcv_mss; app_win = max(app_win, 2U*tp->advmss); - if (!ofo_win) - tp->window_clamp = min(tp->window_clamp, app_win); tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss); } } -- cgit v0.10.2 From 4a7097fcc431ab2ccf509d8342831873138c814a Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Thu, 29 Sep 2005 17:30:54 -0700 Subject: [ATM]: [lec] attempt to support cisco failover From: Scott Talbert Signed-off-by: Chas Williams Signed-off-by: David S. Miller diff --git a/net/atm/lec.c b/net/atm/lec.c index a075248..47e1eae 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -686,9 +686,19 @@ static unsigned char lec_ctrl_magic[] = { 0x01, 0x01 }; +#define LEC_DATA_DIRECT_8023 2 +#define LEC_DATA_DIRECT_8025 3 + +static int lec_is_data_direct(struct atm_vcc *vcc) +{ + return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) || + (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025)); +} + static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) { + unsigned long flags; struct net_device *dev = (struct net_device *)vcc->proto_data; struct lec_priv *priv = (struct lec_priv *)dev->priv; @@ -728,7 +738,8 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); } else { /* Data frame, queue to protocol handlers */ - unsigned char *dst; + struct lec_arp_table *entry; + unsigned char *src, *dst; atm_return(vcc,skb->truesize); if (*(uint16_t *)skb->data == htons(priv->lecid) || @@ -741,10 +752,30 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) return; } #ifdef CONFIG_TR - if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest; + if (priv->is_trdev) + dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest; else #endif - dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest; + dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest; + + /* If this is a Data Direct VCC, and the VCC does not match + * the LE_ARP cache entry, delete the LE_ARP cache entry. + */ + spin_lock_irqsave(&priv->lec_arp_lock, flags); + if (lec_is_data_direct(vcc)) { +#ifdef CONFIG_TR + if (priv->is_trdev) + src = ((struct lecdatahdr_8025 *) skb->data)->h_source; + else +#endif + src = ((struct lecdatahdr_8023 *) skb->data)->h_source; + entry = lec_arp_find(priv, src); + if (entry && entry->vcc != vcc) { + lec_arp_remove(priv, entry); + kfree(entry); + } + } + spin_unlock_irqrestore(&priv->lec_arp_lock, flags); if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ !priv->is_proxy && /* Proxy wants all the packets */ -- cgit v0.10.2 From 75b895c15b3ea2a3cd5c8e8f3c62e4598ef4d2ba Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Thu, 29 Sep 2005 17:31:30 -0700 Subject: [ATM]: [lec] reset retry counter when new arp issued From: Scott Talbert Signed-off-by: Chas Williams Signed-off-by: David S. Miller diff --git a/net/atm/lec.c b/net/atm/lec.c index 47e1eae..ad840b9 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -2021,6 +2021,12 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, found = entry->vcc; goto out; } + /* If the LE_ARP cache entry is still pending, reset count to 0 + * so another LE_ARP request can be made for this frame. + */ + if (entry->status == ESI_ARP_PENDING) { + entry->no_tries = 0; + } /* Data direct VC not yet set up, check to see if the unknown frame count is greater than the limit. If the limit has not been reached, allow the caller to send packet to -- cgit v0.10.2 From 13edad7a5cef1c952459742482482a6b05e1a8a1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Sep 2005 17:58:26 -0700 Subject: [SPARC64]: Rewrite convoluted physical memory probing. Delete all of the code working with sp_banks[] and replace with clean acquisition and sorting of physical memory parameters from the firmware. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 7f190fc..5570e7b 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1333,7 +1333,7 @@ static int cheetah_check_main_memory(unsigned long paddr) { unsigned long vaddr = PAGE_OFFSET + paddr; - if (vaddr > high_memory) + if (vaddr > (unsigned long) high_memory) return 0; return kern_addr_valid(vaddr); diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 48851a2..5db5052 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -41,14 +42,72 @@ extern void device_scan(void); -struct sparc_phys_banks { - unsigned long base_addr; - unsigned long num_bytes; -}; +#define MAX_BANKS 32 + +static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; +static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata; +static int pavail_ents __initdata; +static int pavail_rescan_ents __initdata; + +static int cmp_p64(const void *a, const void *b) +{ + const struct linux_prom64_registers *x = a, *y = b; + + if (x->phys_addr > y->phys_addr) + return 1; + if (x->phys_addr < y->phys_addr) + return -1; + return 0; +} + +static void __init read_obp_memory(const char *property, + struct linux_prom64_registers *regs, + int *num_ents) +{ + int node = prom_finddevice("/memory"); + int prop_size = prom_getproplen(node, property); + int ents, ret, i; + + ents = prop_size / sizeof(struct linux_prom64_registers); + if (ents > MAX_BANKS) { + prom_printf("The machine has more %s property entries than " + "this kernel can support (%d).\n", + property, MAX_BANKS); + prom_halt(); + } + + ret = prom_getproperty(node, property, (char *) regs, prop_size); + if (ret == -1) { + prom_printf("Couldn't get %s property from /memory.\n"); + prom_halt(); + } + + *num_ents = ents; -#define SPARC_PHYS_BANKS 32 + /* Sanitize what we got from the firmware, by page aligning + * everything. + */ + for (i = 0; i < ents; i++) { + unsigned long base, size; + + base = regs[i].phys_addr; + size = regs[i].reg_size; -static struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; + size &= PAGE_MASK; + if (base & ~PAGE_MASK) { + unsigned long new_base = PAGE_ALIGN(base); + + size -= new_base - base; + if ((long) size < 0L) + size = 0UL; + base = new_base; + } + regs[i].phys_addr = base; + regs[i].reg_size = size; + } + sort(regs, ents, sizeof(struct linux_prom64_registers), + cmp_p64, NULL); +} unsigned long *sparc64_valid_addr_bitmap __read_mostly; @@ -1213,14 +1272,14 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) int i; #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("bootmem_init: Scan sp_banks, "); + prom_printf("bootmem_init: Scan pavail, "); #endif bytes_avail = 0UL; - for (i = 0; sp_banks[i].num_bytes != 0; i++) { - end_of_phys_memory = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - bytes_avail += sp_banks[i].num_bytes; + for (i = 0; i < pavail_ents; i++) { + end_of_phys_memory = pavail[i].phys_addr + + pavail[i].reg_size; + bytes_avail += pavail[i].reg_size; if (cmdline_memory_size) { if (bytes_avail > cmdline_memory_size) { unsigned long slack = bytes_avail - cmdline_memory_size; @@ -1228,12 +1287,15 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) bytes_avail -= slack; end_of_phys_memory -= slack; - sp_banks[i].num_bytes -= slack; - if (sp_banks[i].num_bytes == 0) { - sp_banks[i].base_addr = 0xdeadbeef; + pavail[i].reg_size -= slack; + if ((long)pavail[i].reg_size <= 0L) { + pavail[i].phys_addr = 0xdeadbeefUL; + pavail[i].reg_size = 0UL; + pavail_ents = i; } else { - sp_banks[i+1].num_bytes = 0; - sp_banks[i+1].base_addr = 0xdeadbeef; + pavail[i+1].reg_size = 0Ul; + pavail[i+1].phys_addr = 0xdeadbeefUL; + pavail_ents = i + 1; } break; } @@ -1287,12 +1349,12 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) /* Now register the available physical memory with the * allocator. */ - for (i = 0; sp_banks[i].num_bytes != 0; i++) { + for (i = 0; i < pavail_ents; i++) { #ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n", - i, sp_banks[i].base_addr, sp_banks[i].num_bytes); + prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n", + i, pavail[i].phys_addr, pavail[i].reg_size); #endif - free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes); + free_bootmem(pavail[i].phys_addr, pavail[i].reg_size); } #ifdef CONFIG_BLK_DEV_INITRD @@ -1341,7 +1403,7 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, unsigned long alloc_bytes = 0UL; if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { - prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n", + prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n", vstart, vend); prom_halt(); } @@ -1388,23 +1450,24 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, return alloc_bytes; } -extern struct linux_mlist_p1275 *prom_ptot_ptr; +static struct linux_prom64_registers pall[MAX_BANKS] __initdata; +static int pall_ents __initdata; + extern unsigned int kvmap_linear_patch[1]; static void __init kernel_physical_mapping_init(void) { - struct linux_mlist_p1275 *p = prom_ptot_ptr; - unsigned long mem_alloced = 0UL; + unsigned long i, mem_alloced = 0UL; - while (p) { + read_obp_memory("reg", &pall[0], &pall_ents); + + for (i = 0; i < pall_ents; i++) { unsigned long phys_start, phys_end; - phys_start = p->start_adr; - phys_end = phys_start + p->num_bytes; + phys_start = pall[i].phys_addr; + phys_end = phys_start + pall[i].reg_size; mem_alloced += kernel_map_range(phys_start, phys_end, PAGE_KERNEL); - - p = p->theres_more; } printk("Allocated %ld bytes for kernel page tables.\n", @@ -1434,60 +1497,14 @@ void kernel_map_pages(struct page *page, int numpages, int enable) unsigned long __init find_ecache_flush_span(unsigned long size) { - unsigned long i; - - for (i = 0; ; i++) { - if (sp_banks[i].num_bytes == 0) - break; - if (sp_banks[i].num_bytes >= size) - return sp_banks[i].base_addr; - } - - return ~0UL; -} - -static void __init prom_probe_memory(void) -{ - struct linux_mlist_p1275 *mlist; - unsigned long bytes, base_paddr, tally; int i; - i = 0; - mlist = *prom_meminfo()->p1275_available; - bytes = tally = mlist->num_bytes; - base_paddr = mlist->start_adr; - - sp_banks[0].base_addr = base_paddr; - sp_banks[0].num_bytes = bytes; - - while (mlist->theres_more != (void *) 0) { - i++; - mlist = mlist->theres_more; - bytes = mlist->num_bytes; - tally += bytes; - if (i >= SPARC_PHYS_BANKS-1) { - printk ("The machine has more banks than " - "this kernel can support\n" - "Increase the SPARC_PHYS_BANKS " - "setting (currently %d)\n", - SPARC_PHYS_BANKS); - i = SPARC_PHYS_BANKS-1; - break; - } - - sp_banks[i].base_addr = mlist->start_adr; - sp_banks[i].num_bytes = mlist->num_bytes; + for (i = 0; i < pavail_ents; i++) { + if (pavail[i].reg_size >= size) + return pavail[i].phys_addr; } - i++; - sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; - sp_banks[i].num_bytes = 0; - - /* Now mask all bank sizes on a page boundary, it is all we can - * use anyways. - */ - for (i = 0; sp_banks[i].num_bytes != 0; i++) - sp_banks[i].num_bytes &= PAGE_MASK; + return ~0UL; } /* paging_init() sets up the page tables */ @@ -1502,17 +1519,13 @@ void __init paging_init(void) unsigned long end_pfn, pages_avail, shift; unsigned long real_end, i; - prom_probe_memory(); + /* Find available physical memory... */ + read_obp_memory("available", &pavail[0], &pavail_ents); phys_base = 0xffffffffffffffffUL; - for (i = 0; sp_banks[i].num_bytes != 0; i++) { - unsigned long top; + for (i = 0; i < pavail_ents; i++) + phys_base = min(phys_base, pavail[i].phys_addr); - if (sp_banks[i].base_addr < phys_base) - phys_base = sp_banks[i].base_addr; - top = sp_banks[i].base_addr + - sp_banks[i].num_bytes; - } pfn_base = phys_base >> PAGE_SHIFT; kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; @@ -1588,128 +1601,35 @@ void __init paging_init(void) device_scan(); } -/* Ok, it seems that the prom can allocate some more memory chunks - * as a side effect of some prom calls we perform during the - * boot sequence. My most likely theory is that it is from the - * prom_set_traptable() call, and OBP is allocating a scratchpad - * for saving client program register state etc. - */ -static void __init sort_memlist(struct linux_mlist_p1275 *thislist) -{ - int swapi = 0; - int i, mitr; - unsigned long tmpaddr, tmpsize; - unsigned long lowest; - - for (i = 0; thislist[i].theres_more != 0; i++) { - lowest = thislist[i].start_adr; - for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++) - if (thislist[mitr].start_adr < lowest) { - lowest = thislist[mitr].start_adr; - swapi = mitr; - } - if (lowest == thislist[i].start_adr) - continue; - tmpaddr = thislist[swapi].start_adr; - tmpsize = thislist[swapi].num_bytes; - for (mitr = swapi; mitr > i; mitr--) { - thislist[mitr].start_adr = thislist[mitr-1].start_adr; - thislist[mitr].num_bytes = thislist[mitr-1].num_bytes; - } - thislist[i].start_adr = tmpaddr; - thislist[i].num_bytes = tmpsize; - } -} - -void __init rescan_sp_banks(void) -{ - struct linux_prom64_registers memlist[64]; - struct linux_mlist_p1275 avail[64], *mlist; - unsigned long bytes, base_paddr; - int num_regs, node = prom_finddevice("/memory"); - int i; - - num_regs = prom_getproperty(node, "available", - (char *) memlist, sizeof(memlist)); - num_regs = (num_regs / sizeof(struct linux_prom64_registers)); - for (i = 0; i < num_regs; i++) { - avail[i].start_adr = memlist[i].phys_addr; - avail[i].num_bytes = memlist[i].reg_size; - avail[i].theres_more = &avail[i + 1]; - } - avail[i - 1].theres_more = NULL; - sort_memlist(avail); - - mlist = &avail[0]; - i = 0; - bytes = mlist->num_bytes; - base_paddr = mlist->start_adr; - - sp_banks[0].base_addr = base_paddr; - sp_banks[0].num_bytes = bytes; - - while (mlist->theres_more != NULL){ - i++; - mlist = mlist->theres_more; - bytes = mlist->num_bytes; - if (i >= SPARC_PHYS_BANKS-1) { - printk ("The machine has more banks than " - "this kernel can support\n" - "Increase the SPARC_PHYS_BANKS " - "setting (currently %d)\n", - SPARC_PHYS_BANKS); - i = SPARC_PHYS_BANKS-1; - break; - } - - sp_banks[i].base_addr = mlist->start_adr; - sp_banks[i].num_bytes = mlist->num_bytes; - } - - i++; - sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL; - sp_banks[i].num_bytes = 0; - - for (i = 0; sp_banks[i].num_bytes != 0; i++) - sp_banks[i].num_bytes &= PAGE_MASK; -} - static void __init taint_real_pages(void) { - struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS]; int i; - for (i = 0; i < SPARC_PHYS_BANKS; i++) { - saved_sp_banks[i].base_addr = - sp_banks[i].base_addr; - saved_sp_banks[i].num_bytes = - sp_banks[i].num_bytes; - } - - rescan_sp_banks(); + read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents); - /* Find changes discovered in the sp_bank rescan and + /* Find changes discovered in the physmem available rescan and * reserve the lost portions in the bootmem maps. */ - for (i = 0; saved_sp_banks[i].num_bytes; i++) { + for (i = 0; i < pavail_ents; i++) { unsigned long old_start, old_end; - old_start = saved_sp_banks[i].base_addr; + old_start = pavail[i].phys_addr; old_end = old_start + - saved_sp_banks[i].num_bytes; + pavail[i].reg_size; while (old_start < old_end) { int n; - for (n = 0; sp_banks[n].num_bytes; n++) { + for (n = 0; pavail_rescan_ents; n++) { unsigned long new_start, new_end; - new_start = sp_banks[n].base_addr; - new_end = new_start + sp_banks[n].num_bytes; + new_start = pavail_rescan[n].phys_addr; + new_end = new_start + + pavail_rescan[n].reg_size; if (new_start <= old_start && new_end >= (old_start + PAGE_SIZE)) { - set_bit (old_start >> 22, - sparc64_valid_addr_bitmap); + set_bit(old_start >> 22, + sparc64_valid_addr_bitmap); goto do_next_page; } } diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h index 0a33690..b4959d2 100644 --- a/include/asm-sparc64/openprom.h +++ b/include/asm-sparc64/openprom.h @@ -186,8 +186,8 @@ struct linux_prom_registers { }; struct linux_prom64_registers { - long phys_addr; - long reg_size; + unsigned long phys_addr; + unsigned long reg_size; }; struct linux_prom_irqs { -- cgit v0.10.2 From 4cb29d18129fb425c6202ab535c3fc1856391b99 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Sep 2005 18:05:28 -0700 Subject: [SPARC64]: Kill arch/sparc64/prom/memory.c No longer used. Signed-off-by: David S. Miller diff --git a/arch/sparc64/prom/Makefile b/arch/sparc64/prom/Makefile index c7898a5..3d33ed27 100644 --- a/arch/sparc64/prom/Makefile +++ b/arch/sparc64/prom/Makefile @@ -6,5 +6,5 @@ EXTRA_AFLAGS := -ansi EXTRA_CFLAGS := -Werror -lib-y := bootstr.o devops.o init.o memory.o misc.o \ +lib-y := bootstr.o devops.o init.o misc.o \ tree.o console.o printf.o p1275.o cif.o diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c index 8b4b622..f3cc2d8 100644 --- a/arch/sparc64/prom/init.c +++ b/arch/sparc64/prom/init.c @@ -27,7 +27,6 @@ int prom_chosen_node; * failure. It gets passed the pointer to the PROM vector. */ -extern void prom_meminit(void); extern void prom_cif_init(void *, void *); void __init prom_init(void *cif_handler, void *cif_stack) @@ -90,8 +89,6 @@ void __init prom_init(void *cif_handler, void *cif_stack) printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); - prom_meminit(); - /* Initialization successful. */ return; diff --git a/arch/sparc64/prom/memory.c b/arch/sparc64/prom/memory.c deleted file mode 100644 index f4a8143..0000000 --- a/arch/sparc64/prom/memory.c +++ /dev/null @@ -1,152 +0,0 @@ -/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $ - * memory.c: Prom routine for acquiring various bits of information - * about RAM on the machine, both virtual and physical. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include - -#include -#include - -/* This routine, for consistency, returns the ram parameters in the - * V0 prom memory descriptor format. I choose this format because I - * think it was the easiest to work with. I feel the religious - * arguments now... ;) Also, I return the linked lists sorted to - * prevent paging_init() upset stomach as I have not yet written - * the pepto-bismol kernel module yet. - */ - -struct linux_prom64_registers prom_reg_memlist[64]; -struct linux_prom64_registers prom_reg_tmp[64]; - -struct linux_mlist_p1275 prom_phys_total[64]; -struct linux_mlist_p1275 prom_prom_taken[64]; -struct linux_mlist_p1275 prom_phys_avail[64]; - -struct linux_mlist_p1275 *prom_ptot_ptr = prom_phys_total; -struct linux_mlist_p1275 *prom_ptak_ptr = prom_prom_taken; -struct linux_mlist_p1275 *prom_pavl_ptr = prom_phys_avail; - -struct linux_mem_p1275 prom_memlist; - - -/* Internal Prom library routine to sort a linux_mlist_p1275 memory - * list. Used below in initialization. - */ -static void __init -prom_sortmemlist(struct linux_mlist_p1275 *thislist) -{ - int swapi = 0; - int i, mitr; - unsigned long tmpaddr, tmpsize; - unsigned long lowest; - - for(i=0; thislist[i].theres_more; i++) { - lowest = thislist[i].start_adr; - for(mitr = i+1; thislist[mitr-1].theres_more; mitr++) - if(thislist[mitr].start_adr < lowest) { - lowest = thislist[mitr].start_adr; - swapi = mitr; - } - if(lowest == thislist[i].start_adr) continue; - tmpaddr = thislist[swapi].start_adr; - tmpsize = thislist[swapi].num_bytes; - for(mitr = swapi; mitr > i; mitr--) { - thislist[mitr].start_adr = thislist[mitr-1].start_adr; - thislist[mitr].num_bytes = thislist[mitr-1].num_bytes; - } - thislist[i].start_adr = tmpaddr; - thislist[i].num_bytes = tmpsize; - } -} - -/* Initialize the memory lists based upon the prom version. */ -void __init prom_meminit(void) -{ - int node = 0; - unsigned int iter, num_regs; - - node = prom_finddevice("/memory"); - num_regs = prom_getproperty(node, "available", - (char *) prom_reg_memlist, - sizeof(prom_reg_memlist)); - num_regs = (num_regs/sizeof(struct linux_prom64_registers)); - for(iter=0; iter Date: Thu, 29 Sep 2005 18:50:34 -0700 Subject: [SPARC64]: Fix several bugs in flush_ptrace_access(). 1) Use cpudata cache line sizes, not magic constants. 2) Align start address in cheetah case so we do not get unaligned address traps. (pgrep was good at triggering this, via /proc/${pid}/cmdline accesses) Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 5efbff9..774ecbb 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Returning from ptrace is a bit tricky because the syscall return * low level code assumes any value returned which is negative and @@ -132,12 +133,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { unsigned long start = __pa(kaddr); unsigned long end = start + len; + unsigned long dcache_line_size; + + dcache_line_size = local_cpu_data().dcache_line_size; if (tlb_type == spitfire) { - for (; start < end; start += 32) + for (; start < end; start += dcache_line_size) spitfire_put_dcache_tag(start & 0x3fe0, 0x0); } else { - for (; start < end; start += 32) + start &= ~(dcache_line_size - 1); + for (; start < end; start += dcache_line_size) __asm__ __volatile__( "stxa %%g0, [%0] %1\n\t" "membar #Sync" @@ -150,8 +155,11 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, if (write && tlb_type == spitfire) { unsigned long start = (unsigned long) kaddr; unsigned long end = start + len; + unsigned long icache_line_size; + + icache_line_size = local_cpu_data().icache_line_size; - for (; start < end; start += 32) + for (; start < end; start += icache_line_size) flushi(start); } } -- cgit v0.10.2 From 017fb98e70351e9fb5635c299c4d1c50e2f8b823 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Sep 2005 19:26:51 -0700 Subject: [RADEON]: Fix unaligned I/O port access during probe. The driver does a readl() on DEVICE_ID which is 2-byte aligned and 2-bytes in size. It's doing this read just to flush write buffers. Create IN16() and OUT16() macros, and use the former to do this I/O load. Signed-off-by: David S. Miller diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 046b478..8a24a66 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -475,7 +475,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo) */ /* Flush PCI buffers ? */ - tmp = INREG(DEVICE_ID); + tmp = INREG16(DEVICE_ID); local_irq_disable(); diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 659bc9f..01b8b2f 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -395,6 +395,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms) #define INREG8(addr) readb((rinfo->mmio_base)+addr) #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) +#define INREG16(addr) readw((rinfo->mmio_base)+addr) +#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) #define INREG(addr) readl((rinfo->mmio_base)+addr) #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) -- cgit v0.10.2 From 9d30c1718b8baf9a3bb1b81d78afc1e667863477 Mon Sep 17 00:00:00 2001 From: Horms Date: Thu, 29 Sep 2005 19:47:06 -0700 Subject: [IPVS]: Add netdev and me as maintainer contacts Signed-off-by: Horms Signed-off-by: David S. Miller diff --git a/MAINTAINERS b/MAINTAINERS index c1bc9a8..f3d9ade 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1743,8 +1743,11 @@ S: Maintained IPVS P: Wensong Zhang M: wensong@linux-vs.org +P: Simon Horman +M: horms@verge.net.au P: Julian Anastasov M: ja@ssi.bg +L: netdev@vger.kernel.org S: Maintained NFS CLIENT -- cgit v0.10.2 From a4199b0b9aa540a27935251de788cd0f5f5a87aa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 29 Sep 2005 19:49:17 -0700 Subject: [CASSINI]: sparse annotations and fixes - __user annotations - NULL noise removal - C99 initializers - s/u32/pm_message_t/ in ->suspend() - removal of bogus casts in iounmap() arguments - if_mii() instead of open-coded variant Remains to be done: ethtool conversion. Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 69cb368..45831fb 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -3244,7 +3244,7 @@ static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, goto use_random_mac_addr; /* search for beginning of vpd */ - base = 0; + base = NULL; for (i = 2; i < EXPANSION_ROM_SIZE; i++) { /* check for PCIR */ if ((readb(p + i + 0) == 0x50) && @@ -4564,7 +4564,7 @@ static void cas_set_multicast(struct net_device *dev) /* Eventually add support for changing the advertisement * on autoneg. */ -static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) +static int cas_ethtool_ioctl(struct net_device *dev, void __user *ep_user) { struct cas *cp = netdev_priv(dev); u16 bmcr; @@ -4578,7 +4578,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) switch(ecmd.cmd) { case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO }; + struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO }; strncpy(info.driver, DRV_MODULE_NAME, ETHTOOL_BUSINFO_LEN); @@ -4738,7 +4738,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) /* get link status */ case ETHTOOL_GLINK: { - struct ethtool_value edata = { cmd: ETHTOOL_GLINK }; + struct ethtool_value edata = { .cmd = ETHTOOL_GLINK }; edata.data = (cp->lstate == link_up); if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -4748,7 +4748,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) /* get message-level */ case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL }; + struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL }; edata.data = cp->msg_enable; if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -4874,7 +4874,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct cas *cp = netdev_priv(dev); - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + struct mii_ioctl_data *data = if_mii(ifr); unsigned long flags; int rc = -EOPNOTSUPP; @@ -5168,7 +5168,7 @@ err_out_iounmap: cas_shutdown(cp); up(&cp->pm_sem); - iounmap((void *) cp->regs); + iounmap(cp->regs); err_out_free_res: @@ -5216,7 +5216,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) #endif pci_free_consistent(pdev, sizeof(struct cas_init_block), cp->init_block, cp->block_dvma); - iounmap((void *) cp->regs); + iounmap(cp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -5224,7 +5224,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int cas_suspend(struct pci_dev *pdev, u32 state) +static int cas_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct cas *cp = netdev_priv(dev); -- cgit v0.10.2 From 481467d6fa4489aa42321a067e78bad26349488f Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 30 Sep 2005 16:07:04 +0100 Subject: [ARM] 2939/1: Fix compilation error in arch/arm/mm/flush.c Patch from Catalin Marinas When CONFIG_CPU_CACHE_VIPT is defined, the flush_pfn_alias() function is implicitely declared and it later conflicts with its actual definition. This patch moves the function definition to the beginning of the file. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index b0208c9..c9a0398 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -17,6 +17,24 @@ #ifdef CONFIG_CPU_CACHE_VIPT +#define ALIAS_FLUSH_START 0xffff4000 + +#define TOP_PTE(x) pte_offset_kernel(top_pmd, x) + +static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) +{ + unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); + + set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL)); + flush_tlb_kernel_page(to); + + asm( "mcrr p15, 0, %1, %0, c14\n" + " mcrr p15, 0, %1, %0, c5\n" + : + : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES) + : "cc"); +} + void flush_cache_mm(struct mm_struct *mm) { if (cache_is_vivt()) { @@ -67,24 +85,6 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig if (cache_is_vipt_aliasing()) flush_pfn_alias(pfn, user_addr); } - -#define ALIAS_FLUSH_START 0xffff4000 - -#define TOP_PTE(x) pte_offset_kernel(top_pmd, x) - -static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) -{ - unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT); - - set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL)); - flush_tlb_kernel_page(to); - - asm( "mcrr p15, 0, %1, %0, c14\n" - " mcrr p15, 0, %1, %0, c5\n" - : - : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES) - : "cc"); -} #else #define flush_pfn_alias(pfn,vaddr) do { } while (0) #endif -- cgit v0.10.2 From a06f5466c4576dcbf838a50a87903b0082774da7 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 30 Sep 2005 16:07:05 +0100 Subject: [ARM] 2942/1: Fix the warning in arch/arm/common/gic.c Patch from Catalin Marinas The warning is caused by the gic_set_cpu() function being defined but not used if CONFIG_SMP is not defined. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index d749907..c02dc81 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -68,6 +68,7 @@ static void gic_unmask_irq(unsigned int irq) writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4); } +#ifdef CONFIG_SMP static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu) { void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3); @@ -78,6 +79,7 @@ static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu val |= 1 << (cpu + shift); writel(val, reg); } +#endif static struct irqchip gic_chip = { .ack = gic_ack_irq, -- cgit v0.10.2 From 217874feed0d3a6543a6b7127782f4a08bffd731 Mon Sep 17 00:00:00 2001 From: Gen FUKATSU Date: Fri, 30 Sep 2005 16:09:17 +0100 Subject: [ARM] 2940/1: Fix BTB entry flush in arch/arm/mm/cache-v6.S Patch from Gen FUKATSU Invalidate BTB entry instruction flushes two instruction at a time. Therefore this instruction should be done four times after invalidate instruction cache line. Signed-off-by: Gen Fukatsu Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 85c10a7..72966d9 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -18,6 +18,7 @@ #define HARVARD_CACHE #define CACHE_LINE_SIZE 32 #define D_CACHE_LINE_SIZE 32 +#define BTB_FLUSH_SIZE 8 /* * v6_flush_cache_all() @@ -98,7 +99,13 @@ ENTRY(v6_coherent_user_range) mcr p15, 0, r0, c7, c5, 1 @ invalidate I line #endif mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry - add r0, r0, #CACHE_LINE_SIZE + add r0, r0, #BTB_FLUSH_SIZE + mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry + add r0, r0, #BTB_FLUSH_SIZE + mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry + add r0, r0, #BTB_FLUSH_SIZE + mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry + add r0, r0, #BTB_FLUSH_SIZE cmp r0, r1 blo 1b #ifdef HARVARD_CACHE -- cgit v0.10.2 From 192eaa28ba7b44485e521df7ba7a2ccbc4cc4d13 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:15:08 +0100 Subject: [PATCH] missing ERR_PTR in 9fs Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 0957f4d..82c5b00 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -129,7 +129,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); - return newfid; + return ERR_PTR(newfid); } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); -- cgit v0.10.2 From 74ba1fd96666170338dc732480b35b7a83cd164b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:16:43 +0100 Subject: [PATCH] useless linux/irq.h includes (arch/um) Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index c41efd2..189839e 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -7,7 +7,6 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/interrupt.h" -#include "linux/irq.h" #include "linux/spinlock.h" #include "linux/errno.h" #include "asm/atomic.h" diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index dcd8149..bbf94bf 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -9,7 +9,6 @@ #include "linux/kernel.h" #include "linux/module.h" #include "linux/smp.h" -#include "linux/irq.h" #include "linux/kernel_stat.h" #include "linux/interrupt.h" #include "linux/random.h" -- cgit v0.10.2 From 46d7031ecb8a8360b0022abd8014f38cc1197166 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:21:45 +0100 Subject: [PATCH] cassini annotations and fixes - __user annotations - NULL noise removal - C99 initializers - s/u32/pm_message_t/ in ->suspend() - removal of bogus casts in iounmap() arguments - if_mii() instead of open-coded variant Remains to be done: ethtool conversion. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 69cb368..45831fb 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -3244,7 +3244,7 @@ static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr, goto use_random_mac_addr; /* search for beginning of vpd */ - base = 0; + base = NULL; for (i = 2; i < EXPANSION_ROM_SIZE; i++) { /* check for PCIR */ if ((readb(p + i + 0) == 0x50) && @@ -4564,7 +4564,7 @@ static void cas_set_multicast(struct net_device *dev) /* Eventually add support for changing the advertisement * on autoneg. */ -static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) +static int cas_ethtool_ioctl(struct net_device *dev, void __user *ep_user) { struct cas *cp = netdev_priv(dev); u16 bmcr; @@ -4578,7 +4578,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) switch(ecmd.cmd) { case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO }; + struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO }; strncpy(info.driver, DRV_MODULE_NAME, ETHTOOL_BUSINFO_LEN); @@ -4738,7 +4738,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) /* get link status */ case ETHTOOL_GLINK: { - struct ethtool_value edata = { cmd: ETHTOOL_GLINK }; + struct ethtool_value edata = { .cmd = ETHTOOL_GLINK }; edata.data = (cp->lstate == link_up); if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -4748,7 +4748,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) /* get message-level */ case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL }; + struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL }; edata.data = cp->msg_enable; if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -4874,7 +4874,7 @@ static int cas_ethtool_ioctl(struct net_device *dev, void *ep_user) static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct cas *cp = netdev_priv(dev); - struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + struct mii_ioctl_data *data = if_mii(ifr); unsigned long flags; int rc = -EOPNOTSUPP; @@ -5168,7 +5168,7 @@ err_out_iounmap: cas_shutdown(cp); up(&cp->pm_sem); - iounmap((void *) cp->regs); + iounmap(cp->regs); err_out_free_res: @@ -5216,7 +5216,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) #endif pci_free_consistent(pdev, sizeof(struct cas_init_block), cp->init_block, cp->block_dvma); - iounmap((void *) cp->regs); + iounmap(cp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -5224,7 +5224,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int cas_suspend(struct pci_dev *pdev, u32 state) +static int cas_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct cas *cp = netdev_priv(dev); -- cgit v0.10.2 From eacaa1f5aa4a41a48349f55abcd9258506943e76 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:26:43 +0100 Subject: [PATCH] cpuset crapectomy Switched cpuset_common_file_read() to simple_read_from_buffer(), killed a bunch of useless (and not quite correct - e.g. min(size_t,ssize_t)) code. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 6a6e87b..45a5719 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -968,8 +968,6 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, char *page; ssize_t retval = 0; char *s; - char *start; - ssize_t n; if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; @@ -999,15 +997,7 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, *s++ = '\n'; *s = '\0'; - start = page + *ppos; - n = s - start; - - /* Do nothing if *ppos is at the eof or beyond the eof. */ - if (n <= 0) - goto out; - - retval = n - copy_to_user(buf, start, min(n, nbytes)); - *ppos += retval; + retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page); out: free_page((unsigned long)page); return retval; -- cgit v0.10.2 From 4735885701d7c24ed54f35f5102d32b3aabee55e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:29:05 +0100 Subject: [PATCH] uml get_user() NULL noise removal Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h index 801710d..2ee028b 100644 --- a/include/asm-um/uaccess.h +++ b/include/asm-um/uaccess.h @@ -44,7 +44,7 @@ const __typeof__(ptr) __private_ptr = ptr; \ __typeof__(*(__private_ptr)) __private_val; \ int __private_ret = -EFAULT; \ - (x) = 0; \ + (x) = (__typeof__(*(__private_ptr)))0; \ if (__copy_from_user(&__private_val, (__private_ptr), \ sizeof(*(__private_ptr))) == 0) {\ (x) = (__typeof__(*(__private_ptr))) __private_val; \ -- cgit v0.10.2 From c215a16a4ad620b612b51495cbb99dbbb59bb585 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 03:36:50 +0100 Subject: [PATCH] bogus BUILD_BUG_ON() in bpa_iommu BUILD_BUG_ON(1) is asking for trouble (and getting it) when used in that manner - dead code elimination happens after we parse it and invalid type is invalid type, dead code or not. It might be version-dependent, but at least 4.0.1 refuses to accept that. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c index f33a7bc..507eb9d 100644 --- a/arch/ppc64/kernel/bpa_iommu.c +++ b/arch/ppc64/kernel/bpa_iommu.c @@ -99,7 +99,11 @@ get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_ break; default: /* not a known compile time constant */ - BUILD_BUG_ON(1); + { + /* BUILD_BUG_ON() is not usable here */ + extern void __get_iost_entry_bad_page_size(void); + __get_iost_entry_bad_page_size(); + } break; } -- cgit v0.10.2 From 66df3bbf0701b7408a1067c4b819aceee2686bba Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 04:19:43 +0100 Subject: [PATCH] volatile unsigned short f(...) doesn't make sense Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 8dc657f..60dba4a 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -218,7 +218,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data ) static inline -volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset ) +unsigned short bmread(struct net_device *dev, unsigned long reg_offset ) { return in_le16((void __iomem *)dev->base_addr + reg_offset); } -- cgit v0.10.2 From a3ca066efb18524bf3f07137a8f8ff434022c4f2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 04:20:57 +0100 Subject: [PATCH] missing qualifiers in readb() et.al. on ppc Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index 7eb7cf6..94d8399 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -56,7 +56,7 @@ extern unsigned long pci_dram_offset; * is actually performed (i.e. the data has come back) before we start * executing any following instructions. */ -extern inline int in_8(volatile unsigned char __iomem *addr) +extern inline int in_8(const volatile unsigned char __iomem *addr) { int ret; @@ -72,7 +72,7 @@ extern inline void out_8(volatile unsigned char __iomem *addr, int val) __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); } -extern inline int in_le16(volatile unsigned short __iomem *addr) +extern inline int in_le16(const volatile unsigned short __iomem *addr) { int ret; @@ -83,7 +83,7 @@ extern inline int in_le16(volatile unsigned short __iomem *addr) return ret; } -extern inline int in_be16(volatile unsigned short __iomem *addr) +extern inline int in_be16(const volatile unsigned short __iomem *addr) { int ret; @@ -104,7 +104,7 @@ extern inline void out_be16(volatile unsigned short __iomem *addr, int val) __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); } -extern inline unsigned in_le32(volatile unsigned __iomem *addr) +extern inline unsigned in_le32(const volatile unsigned __iomem *addr) { unsigned ret; @@ -115,7 +115,7 @@ extern inline unsigned in_le32(volatile unsigned __iomem *addr) return ret; } -extern inline unsigned in_be32(volatile unsigned __iomem *addr) +extern inline unsigned in_be32(const volatile unsigned __iomem *addr) { unsigned ret; @@ -139,7 +139,7 @@ extern inline void out_be32(volatile unsigned __iomem *addr, int val) #define readb(addr) in_8((volatile u8 *)(addr)) #define writeb(b,addr) out_8((volatile u8 *)(addr), (b)) #else -static inline __u8 readb(volatile void __iomem *addr) +static inline __u8 readb(const volatile void __iomem *addr) { return in_8(addr); } @@ -150,11 +150,11 @@ static inline void writeb(__u8 b, volatile void __iomem *addr) #endif #if defined(CONFIG_APUS) -static inline __u16 readw(volatile void __iomem *addr) +static inline __u16 readw(const volatile void __iomem *addr) { return *(__force volatile __u16 *)(addr); } -static inline __u32 readl(volatile void __iomem *addr) +static inline __u32 readl(const volatile void __iomem *addr) { return *(__force volatile __u32 *)(addr); } @@ -173,11 +173,11 @@ static inline void writel(__u32 b, volatile void __iomem *addr) #define writew(b,addr) out_le16((volatile u16 *)(addr),(b)) #define writel(b,addr) out_le32((volatile u32 *)(addr),(b)) #else -static inline __u16 readw(volatile void __iomem *addr) +static inline __u16 readw(const volatile void __iomem *addr) { return in_le16(addr); } -static inline __u32 readl(volatile void __iomem *addr) +static inline __u32 readl(const volatile void __iomem *addr) { return in_le32(addr); } -- cgit v0.10.2 From 794fb8370db3d5f26592b9b45d69aeca2f583efb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Sep 2005 05:09:34 +0100 Subject: [PATCH] useless includes of linux/irq.h (arch/ppc) Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c index ac391d4..78a403b 100644 --- a/arch/ppc/platforms/4xx/bamboo.c +++ b/arch/ppc/platforms/4xx/bamboo.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index d6b2b19..27b778a 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index a38e6f9..16d953b 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 80028df..506949c 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c index b38a851..79b3f53 100644 --- a/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c index f761fdf..7dc8a68 100644 --- a/arch/ppc/platforms/85xx/mpc8540_ads.c +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index f2748c8..8841fd7 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c index 18e952d..bd3ac01 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 6267b29..9f90394 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 165df94..c76760a 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c index 4f6d1dd..c02f110 100644 --- a/arch/ppc/platforms/85xx/sbc85xx.c +++ b/arch/ppc/platforms/85xx/sbc85xx.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index c99b365..20940f4 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c index 7786818..df6ff98 100644 --- a/arch/ppc/platforms/chestnut.c +++ b/arch/ppc/platforms/chestnut.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 57f29ab..66346f0 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c index e391e52..3a5ff9f 100644 --- a/arch/ppc/platforms/gemini_setup.c +++ b/arch/ppc/platforms/gemini_setup.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c index b292b44..ce2ce88 100644 --- a/arch/ppc/platforms/mvme5100.c +++ b/arch/ppc/platforms/mvme5100.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index 4c56a47..d6356f4 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c index 0abe151..e6b520e 100644 --- a/arch/ppc/platforms/powerpmc250.c +++ b/arch/ppc/platforms/powerpmc250.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c index 65705c9..e70aae2 100644 --- a/arch/ppc/platforms/pplus.c +++ b/arch/ppc/platforms/pplus.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c index 24ae1ca..0bb14a5 100644 --- a/arch/ppc/platforms/prpmc750.c +++ b/arch/ppc/platforms/prpmc750.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c index 8b09fa6..de7baef 100644 --- a/arch/ppc/platforms/prpmc800.c +++ b/arch/ppc/platforms/prpmc800.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index c30607a..0376c8c 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -59,7 +58,6 @@ #include #include #include -#include #include "radstone_ppc7d.h" diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c index 21e3134..5232283 100644 --- a/arch/ppc/platforms/sandpoint.c +++ b/arch/ppc/platforms/sandpoint.c @@ -74,7 +74,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 53da585..1cf5de2 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 9a7e874..16cff91 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c index b843c4f..bf83240 100644 --- a/arch/ppc/syslib/ppc4xx_setup.c +++ b/arch/ppc/syslib/ppc4xx_setup.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 1294b118cb53fb14515666e2b218ad5ab40318c1 Mon Sep 17 00:00:00 2001 From: Kirill Korotaev Date: Fri, 30 Sep 2005 10:32:19 +0400 Subject: [PATCH] x86_64: Add missing () around arguments of pte_index macro x86-64: Add missing () around arguments of pte_index macro Signed-Off-By: Alexey Kuznetsov Signed-Off-By: Kirill Korotaev Signed-off-by: Linus Torvalds diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 2cb4835..dd8711e 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -384,7 +384,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) } #define pte_index(address) \ - ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \ pte_index(address)) -- cgit v0.10.2 From 03cdc0c304e1c068d49adc32264f07af76253e4c Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Thu, 29 Sep 2005 21:39:32 +0200 Subject: [PATCH] usb/core/hcd-pci.c: don't free_irq() on suspend the free_irq() in USB suspend breaks resume on some setups where USB (ohci/ehci) shares the interrupt with an other device. Signed-off-by: Daniel Ritz Signed-off-by: Linus Torvalds diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index cbb451d..6385d1a 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -242,7 +242,6 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) case HC_STATE_SUSPENDED: /* no DMA or IRQs except when HC is active */ if (dev->current_state == PCI_D0) { - free_irq (hcd->irq, hcd); pci_save_state (dev); pci_disable_device (dev); } @@ -374,14 +373,6 @@ int usb_hcd_pci_resume (struct pci_dev *dev) hcd->state = HC_STATE_RESUMING; hcd->saw_irq = 0; - retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, - hcd->irq_descr, hcd); - if (retval < 0) { - dev_err (hcd->self.controller, - "can't restore IRQ after resume!\n"); - usb_hc_died (hcd); - return retval; - } retval = hcd->driver->resume (hcd); if (!HC_IS_RUNNING (hcd->state)) { -- cgit v0.10.2 From b33fa1f3c3ec05e54e73f06c4578948c55d89ef6 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Sat, 1 Oct 2005 02:34:42 +1000 Subject: [PATCH] i386: include linux/irq.h rather than asm/hw_irq.h I need the following patch to compile -git8 here, otherwise these files fail to compile (asm/hw_irq.h needs definitions from linux/irq.h and that file provides the required include ordering). I did not do a full audit, though there looks to be many other places that should get the same treatment, if this is the right way to do it. Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 838437b2..b66c13c 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -29,12 +29,12 @@ #include #include #include +#include #include #include #include #include -#include #include #ifdef CONFIG_X86_64 diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c index 7e7a202..4c4522b 100644 --- a/arch/i386/pci/acpi.c +++ b/arch/i386/pci/acpi.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include "pci.h" diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 281ed8a..cddafe3 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include "pci.h" -- cgit v0.10.2 From 13402580021a52e49c6d1068ff28ade4d5a175f1 Mon Sep 17 00:00:00 2001 From: James Morris Date: Fri, 30 Sep 2005 14:24:34 -0400 Subject: [PATCH] SELinux - fix SCTP socket bug and general IP protocol handling The following patch updates the way SELinux classifies and handles IP based protocols. Currently, IP sockets are classified by SELinux as being either TCP, UDP or 'Raw', the latter being a default for IP socket that is not TCP or UDP. The classification code is out of date and uses only the socket type parameter to socket(2) to determine the class of IP socket. So, any socket created with SOCK_STREAM will be classified by SELinux as TCP, and SOCK_DGRAM as UDP. Also, other socket types such as SOCK_SEQPACKET and SOCK_DCCP are currently ignored by SELinux, which classifies them as generic sockets, which means they don't even get basic IP level checking. This patch changes the SELinux IP socket classification logic, so that only an IPPROTO_IP protocol value passed to socket(2) classify the socket as TCP or UDP. The patch also drops the check for SOCK_RAW and converts it into a default, so that socket types like SOCK_DCCP and SOCK_SEQPACKET are classified as SECCLASS_RAWIP_SOCKET (instead of generic sockets). Note that protocol-specific support for SCTP, DCCP etc. is not addressed here, we're just getting these protocols checked at the IP layer. This fixes a reported problem where SCTP sockets were being recognized as generic SELinux sockets yet still being passed in one case to an IP level check, which then fails for generic sockets. It will also fix bugs where any SOCK_STREAM socket is classified as TCP or any SOCK_DGRAM socket is classified as UDP. This patch also unifies the way IP sockets classes are determined in selinux_socket_bind(), so we use the already calculated value instead of trying to recalculate it. Signed-off-by: James Morris Signed-off-by: Stephen Smalley Signed-off-by: Linus Torvalds diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6e4937f..b13be15 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -630,6 +630,16 @@ static inline u16 inode_mode_to_security_class(umode_t mode) return SECCLASS_FILE; } +static inline int default_protocol_stream(int protocol) +{ + return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP); +} + +static inline int default_protocol_dgram(int protocol) +{ + return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP); +} + static inline u16 socket_type_to_security_class(int family, int type, int protocol) { switch (family) { @@ -646,10 +656,16 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc case PF_INET6: switch (type) { case SOCK_STREAM: - return SECCLASS_TCP_SOCKET; + if (default_protocol_stream(protocol)) + return SECCLASS_TCP_SOCKET; + else + return SECCLASS_RAWIP_SOCKET; case SOCK_DGRAM: - return SECCLASS_UDP_SOCKET; - case SOCK_RAW: + if (default_protocol_dgram(protocol)) + return SECCLASS_UDP_SOCKET; + else + return SECCLASS_RAWIP_SOCKET; + default: return SECCLASS_RAWIP_SOCKET; } break; @@ -2970,6 +2986,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in /* * If PF_INET or PF_INET6, check name_bind permission for the port. + * Multiple address binding for SCTP is not supported yet: we just + * check the first address now. */ family = sock->sk->sk_family; if (family == PF_INET || family == PF_INET6) { @@ -3014,12 +3032,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in goto out; } - switch(sk->sk_protocol) { - case IPPROTO_TCP: + switch(isec->sclass) { + case SECCLASS_TCP_SOCKET: node_perm = TCP_SOCKET__NODE_BIND; break; - case IPPROTO_UDP: + case SECCLASS_UDP_SOCKET: node_perm = UDP_SOCKET__NODE_BIND; break; -- cgit v0.10.2 From 6e3254c4e2927c117044a02acf5f5b56e1373053 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Sep 2005 12:38:27 -0700 Subject: Revert "x86-64: Reverse order of bootmem lists" As requested by Thomas Gleixner : "5d3d0f7704ed0bc7eaca0501eeae3e5da1ea6c87 breaks a couple of ARM boards, which depend on the historical bootmem allocation order. There is a cleaner solution around to remove the pgdat list completely, but this is a topic for post 2.6.14 Andi signalled ACK already." Signed-off-by: Linus Torvalds diff --git a/mm/bootmem.c b/mm/bootmem.c index 8ec4e4c..c1330cc 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -61,17 +61,9 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat, { bootmem_data_t *bdata = pgdat->bdata; unsigned long mapsize = ((end - start)+7)/8; - static struct pglist_data *pgdat_last; - - pgdat->pgdat_next = NULL; - /* Add new nodes last so that bootmem always starts - searching in the first nodes, not the last ones */ - if (pgdat_last) - pgdat_last->pgdat_next = pgdat; - else { - pgdat_list = pgdat; - pgdat_last = pgdat; - } + + pgdat->pgdat_next = pgdat_list; + pgdat_list = pgdat; mapsize = ALIGN(mapsize, sizeof(long)); bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT); -- cgit v0.10.2 From 998765e5588b197737d457e16f72832d8036190f Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 30 Sep 2005 11:58:54 -0700 Subject: [PATCH] aio: lock around kiocbTryKick() Only one of the run or kick path is supposed to put an iocb on the run list. If both of them do it than one of them can end up referencing a freed iocb. The kick patch could set the Kicked bit before acquiring the ctx_lock and putting the iocb on the run list. The run path, while holding the ctx_lock, could see this partial kick and mistake it for a kick that was deferred while it was doing work with the run_list NULLed out. It would then race with the kick thread to add the iocb to the run list. This patch moves the kick setting under the ctx_lock so that only one of the kick or run path queues the iocb on the run list, as intended. Signed-off-by: Zach Brown Signed-off-by: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/aio.c b/fs/aio.c index 0e11e31..b8f2969 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -899,16 +899,24 @@ static void aio_kick_handler(void *data) * and if required activate the aio work queue to process * it */ -static void queue_kicked_iocb(struct kiocb *iocb) +static void try_queue_kicked_iocb(struct kiocb *iocb) { struct kioctx *ctx = iocb->ki_ctx; unsigned long flags; int run = 0; - WARN_ON((!list_empty(&iocb->ki_wait.task_list))); + /* We're supposed to be the only path putting the iocb back on the run + * list. If we find that the iocb is *back* on a wait queue already + * than retry has happened before we could queue the iocb. This also + * means that the retry could have completed and freed our iocb, no + * good. */ + BUG_ON((!list_empty(&iocb->ki_wait.task_list))); spin_lock_irqsave(&ctx->ctx_lock, flags); - run = __queue_kicked_iocb(iocb); + /* set this inside the lock so that we can't race with aio_run_iocb() + * testing it and putting the iocb on the run list under the lock */ + if (!kiocbTryKick(iocb)) + run = __queue_kicked_iocb(iocb); spin_unlock_irqrestore(&ctx->ctx_lock, flags); if (run) aio_queue_work(ctx); @@ -931,10 +939,7 @@ void fastcall kick_iocb(struct kiocb *iocb) return; } - /* If its already kicked we shouldn't queue it again */ - if (!kiocbTryKick(iocb)) { - queue_kicked_iocb(iocb); - } + try_queue_kicked_iocb(iocb); } EXPORT_SYMBOL(kick_iocb); -- cgit v0.10.2 From 897f15fb587fd2772b9e7ff6ec0265057f3c3975 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 30 Sep 2005 11:58:55 -0700 Subject: [PATCH] aio: remove unlocked task_list test and resulting race Only one of the run or kick path is supposed to put an iocb on the run list. If both of them do it than one of them can end up referencing a freed iocb. The kick path could delete the task_list item from the wait queue before getting the ctx_lock and putting the iocb on the run list. The run path was testing the task_list item outside the lock so that it could catch ki_retry methods that return -EIOCBRETRY *without* putting the iocb on a wait queue and promising to call kick_iocb. This unlocked check could then race with the kick path to cause both to try and put the iocb on the run list. The patch stops the run path from testing task_list by requring that any ki_retry that returns -EIOCBRETRY *must* guarantee that kick_iocb() will be called in the future. aio_p{read,write}, the only in-tree -EIOCBRETRY users, are updated. Signed-off-by: Zach Brown Signed-off-by: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/aio.c b/fs/aio.c index b8f2969..9edc0e4 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -741,19 +741,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) ret = retry(iocb); current->io_wait = NULL; - if (-EIOCBRETRY != ret) { - if (-EIOCBQUEUED != ret) { - BUG_ON(!list_empty(&iocb->ki_wait.task_list)); - aio_complete(iocb, ret, 0); - /* must not access the iocb after this */ - } - } else { - /* - * Issue an additional retry to avoid waiting forever if - * no waits were queued (e.g. in case of a short read). - */ - if (list_empty(&iocb->ki_wait.task_list)) - kiocbSetKicked(iocb); + if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { + BUG_ON(!list_empty(&iocb->ki_wait.task_list)); + aio_complete(iocb, ret, 0); } out: spin_lock_irq(&ctx->ctx_lock); @@ -1327,8 +1317,11 @@ asmlinkage long sys_io_destroy(aio_context_t ctx) } /* - * Default retry method for aio_read (also used for first time submit) - * Responsible for updating iocb state as retries progress + * aio_p{read,write} are the default ki_retry methods for + * IO_CMD_P{READ,WRITE}. They maintains kiocb retry state around potentially + * multiple calls to f_op->aio_read(). They loop around partial progress + * instead of returning -EIOCBRETRY because they don't have the means to call + * kick_iocb(). */ static ssize_t aio_pread(struct kiocb *iocb) { @@ -1337,25 +1330,25 @@ static ssize_t aio_pread(struct kiocb *iocb) struct inode *inode = mapping->host; ssize_t ret = 0; - ret = file->f_op->aio_read(iocb, iocb->ki_buf, - iocb->ki_left, iocb->ki_pos); + do { + ret = file->f_op->aio_read(iocb, iocb->ki_buf, + iocb->ki_left, iocb->ki_pos); + /* + * Can't just depend on iocb->ki_left to determine + * whether we are done. This may have been a short read. + */ + if (ret > 0) { + iocb->ki_buf += ret; + iocb->ki_left -= ret; + } - /* - * Can't just depend on iocb->ki_left to determine - * whether we are done. This may have been a short read. - */ - if (ret > 0) { - iocb->ki_buf += ret; - iocb->ki_left -= ret; /* - * For pipes and sockets we return once we have - * some data; for regular files we retry till we - * complete the entire read or find that we can't - * read any more data (e.g short reads). + * For pipes and sockets we return once we have some data; for + * regular files we retry till we complete the entire read or + * find that we can't read any more data (e.g short reads). */ - if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)) - ret = -EIOCBRETRY; - } + } while (ret > 0 && + !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)); /* This means we must have transferred all that we could */ /* No need to retry anymore */ @@ -1365,27 +1358,21 @@ static ssize_t aio_pread(struct kiocb *iocb) return ret; } -/* - * Default retry method for aio_write (also used for first time submit) - * Responsible for updating iocb state as retries progress - */ +/* see aio_pread() */ static ssize_t aio_pwrite(struct kiocb *iocb) { struct file *file = iocb->ki_filp; ssize_t ret = 0; - ret = file->f_op->aio_write(iocb, iocb->ki_buf, - iocb->ki_left, iocb->ki_pos); - - if (ret > 0) { - iocb->ki_buf += ret; - iocb->ki_left -= ret; - - ret = -EIOCBRETRY; - } + do { + ret = file->f_op->aio_write(iocb, iocb->ki_buf, + iocb->ki_left, iocb->ki_pos); + if (ret > 0) { + iocb->ki_buf += ret; + iocb->ki_left -= ret; + } + } while (ret > 0); - /* This means we must have transferred all that we could */ - /* No need to retry anymore */ if ((ret == 0) || (iocb->ki_left == 0)) ret = iocb->ki_nbytes - iocb->ki_left; diff --git a/include/linux/aio.h b/include/linux/aio.h index a4d5af9..60def65 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -43,6 +43,40 @@ struct kioctx; #define kiocbIsKicked(iocb) test_bit(KIF_KICKED, &(iocb)->ki_flags) #define kiocbIsCancelled(iocb) test_bit(KIF_CANCELLED, &(iocb)->ki_flags) +/* is there a better place to document function pointer methods? */ +/** + * ki_retry - iocb forward progress callback + * @kiocb: The kiocb struct to advance by performing an operation. + * + * This callback is called when the AIO core wants a given AIO operation + * to make forward progress. The kiocb argument describes the operation + * that is to be performed. As the operation proceeds, perhaps partially, + * ki_retry is expected to update the kiocb with progress made. Typically + * ki_retry is set in the AIO core and it itself calls file_operations + * helpers. + * + * ki_retry's return value determines when the AIO operation is completed + * and an event is generated in the AIO event ring. Except the special + * return values described below, the value that is returned from ki_retry + * is transferred directly into the completion ring as the operation's + * resulting status. Once this has happened ki_retry *MUST NOT* reference + * the kiocb pointer again. + * + * If ki_retry returns -EIOCBQUEUED it has made a promise that aio_complete() + * will be called on the kiocb pointer in the future. The AIO core will + * not ask the method again -- ki_retry must ensure forward progress. + * aio_complete() must be called once and only once in the future, multiple + * calls may result in undefined behaviour. + * + * If ki_retry returns -EIOCBRETRY it has made a promise that kick_iocb() + * will be called on the kiocb pointer in the future. This may happen + * through generic helpers that associate kiocb->ki_wait with a wait + * queue head that ki_retry uses via current->io_wait. It can also happen + * with custom tracking and manual calls to kick_iocb(), though that is + * discouraged. In either case, kick_iocb() must be called once and only + * once. ki_retry must ensure forward progress, the AIO core will wait + * indefinitely for kick_iocb() to be called. + */ struct kiocb { struct list_head ki_run_list; long ki_flags; -- cgit v0.10.2 From 353fb07e2043d2df12dddf4e2c39552d0ab9b026 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 30 Sep 2005 11:58:56 -0700 Subject: [PATCH] aio: avoid extra aio_{read,write} call when ki_left == 0 Recently aio_p{read,write} changed to perform retries internally rather than returning -EIOCBRETRY. This inadvertantly resulted in always calling aio_{read,write} with ki_left at 0 which would in turn immediately return 0. Harmless, but we can avoid this call by checking in the caller. Signed-off-by: Zach Brown Signed-off-by: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/aio.c b/fs/aio.c index 9edc0e4..d6b1551 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1347,7 +1347,7 @@ static ssize_t aio_pread(struct kiocb *iocb) * regular files we retry till we complete the entire read or * find that we can't read any more data (e.g short reads). */ - } while (ret > 0 && + } while (ret > 0 && iocb->ki_left > 0 && !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)); /* This means we must have transferred all that we could */ @@ -1371,7 +1371,7 @@ static ssize_t aio_pwrite(struct kiocb *iocb) iocb->ki_buf += ret; iocb->ki_left -= ret; } - } while (ret > 0); + } while (ret > 0 && iocb->ki_left > 0); if ((ret == 0) || (iocb->ki_left == 0)) ret = iocb->ki_nbytes - iocb->ki_left; -- cgit v0.10.2 From d96c4e7bb039ae16c9b7e6809feb4fcfc45fcc87 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 30 Sep 2005 11:58:57 -0700 Subject: [PATCH] x86: hw_irq.h warning fix include/asm/hw_irq.h:70: warning: `struct hw_interrupt_type' declared inside parameter list include/asm/hw_irq.h:70: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index 4ac84cc..622815b 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -18,6 +18,8 @@ #include #include +struct hw_interrupt_type; + /* * Various low-level irq details needed by irq.c, process.c, * time.c, io_apic.c and smp.c -- cgit v0.10.2 From 79dfa4a5a2eea5035de793b1633031750fe8d3ff Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 30 Sep 2005 11:58:58 -0700 Subject: [PATCH] v4l: DViCO FusionHDTV5 Lite GPIO Fix GPIO fix for the composite and tv mute states of bt8xx card #135: DViCO FusionHDTV5 Lite. Without this patch, selecting one of these states could produce unexpected behavior. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 190977a..6c33280 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2398,7 +2398,7 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .muxsel = { 2, 3 }, .gpiomask = 0x00e00007, - .audiomux = { 0x00400005, 0, 0, 0, 0, 0 }, + .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, .no_msp34xx = 1, .no_tda9875 = 1, .no_tda7432 = 1, -- cgit v0.10.2 From be662a18b7763496a052d489206af9ca2c2e1ac2 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Fri, 30 Sep 2005 11:58:59 -0700 Subject: [PATCH] uml: fix page faults in SKAS3 mode. I hadn't been running a SKAS3 host when testing the "uml: fix hang in TT mode on fault" patch (commit 546fe1cbf91d4d62e3849517c31a2327c992e5c5), and I didn't think enough to the missing trap_no in SKAS3 mode. In fact, the resulting kernel doesn't work at all in SKAS3 mode. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 1fe7292..23fd264 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h @@ -6,6 +6,7 @@ #ifndef __SYS_SIGCONTEXT_I386_H #define __SYS_SIGCONTEXT_I386_H +#include "uml-config.h" #include #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) @@ -26,7 +27,14 @@ #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) /* This is Page Fault */ -#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) +#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) + +/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ +#ifdef UML_CONFIG_MODE_SKAS +#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) +#else +#define SEGV_MAYBE_FIXABLE(fi) 0 +#endif extern unsigned long *sc_sigmask(void *sc_ptr); extern int sc_get_fpregs(unsigned long buf, void *sc_ptr); diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h index 2a78260..4107323 100644 --- a/arch/um/include/sysdep-x86_64/sigcontext.h +++ b/arch/um/include/sysdep-x86_64/sigcontext.h @@ -31,7 +31,10 @@ #define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0) /* This is Page Fault */ -#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) +#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) + +/* No broken SKAS API, which doesn't pass trap_no, here. */ +#define SEGV_MAYBE_FIXABLE(fi) 0 extern unsigned long *sc_sigmask(void *sc_ptr); diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index d297429..95c8f87 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -26,6 +26,9 @@ #include "mconsole_kern.h" #include "mem.h" #include "mem_kern.h" +#ifdef CONFIG_MODE_SKAS +#include "skas.h" +#endif /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ int handle_page_fault(unsigned long address, unsigned long ip, @@ -134,7 +137,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) else if(current->mm == NULL) panic("Segfault with no mm"); - if (SEGV_IS_FIXABLE(&fi)) + if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); else { err = -EFAULT; -- cgit v0.10.2 From 8923648c125421b0fcb240cde607e2748d099ab8 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Fri, 30 Sep 2005 11:59:00 -0700 Subject: [PATCH] uml: clear SKAS0/3 flags when running in TT mode SEGV_MAYBE_FIXABLE tests ptrace_faultinfo, and depends on it being 1 only in SKAS3 mode, while currently when running with mode=tt it will be 1 anyway. Fix this, and do the same for proc_mm. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 583329d..6f766e1 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -157,6 +157,10 @@ extern int os_lock_file(int fd, int excl); extern void os_early_checks(void); extern int can_do_skas(void); +/* Make sure they are clear when running in TT mode. Required by + * SEGV_MAYBE_FIXABLE */ +#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) + /* mem.c */ extern int create_mem_file(unsigned long len); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index f0a2759..93dc782 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -334,6 +334,8 @@ int linux_main(int argc, char **argv) add_arg(DEFAULT_COMMAND_LINE); os_early_checks(); + if (force_tt) + clear_can_do_skas(); mode_tt = force_tt ? 1 : !can_do_skas(); #ifndef CONFIG_MODE_TT if (mode_tt) { -- cgit v0.10.2 From bd948057357db5febfe64cf7a9ef11d7e347ffec Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Fri, 30 Sep 2005 11:59:00 -0700 Subject: [PATCH] uml: revert "run mconsole "sysrq" in process context" Revert commit 12ebcd73e40e09f0dfddf89e465cc0541e0ff8b1, i.e. [PATCH] uml: run mconsole "sysrq" in process context on request from Jeff Dike. a) sysrq may be run when the scheduler is non-functioning b) the warning I wanted to fix actually came from the fault handler run in atomic context. But I fixed that not to take the semaphore in a separate patch. c) the fault handler is run because of a fault, and that fault was unaffected by this patch. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index 04383f9..310c1f8 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -23,7 +23,7 @@ static struct mconsole_command commands[] = { { "reboot", mconsole_reboot, MCONSOLE_PROC }, { "config", mconsole_config, MCONSOLE_PROC }, { "remove", mconsole_remove, MCONSOLE_PROC }, - { "sysrq", mconsole_sysrq, MCONSOLE_PROC }, + { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, { "help", mconsole_help, MCONSOLE_INTR }, { "cad", mconsole_cad, MCONSOLE_INTR }, { "stop", mconsole_stop, MCONSOLE_PROC }, -- cgit v0.10.2 From daa35edc0a967d1f77c2e2c1346f57d04371487a Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Fri, 30 Sep 2005 11:59:01 -0700 Subject: [PATCH] uml: remove empty hostfs_truncate method Calling truncate() on hostfs spits a kernel warning "Something isn't implemented here", but it still works fine. Indeed, hostfs i_op->truncate doesn't do anything. But hostfs_setattr() -> set_attr() correctly detects ATTR_SIZE and calls truncate() on the host. So we should be safe (using ftruncate() may be better, in case the file is unlinked on the host, but we aren't sure to have the file open for writing, and reopening it would cause the same races; plus nobody should expect UML to be so careful). So, the warning is wrong, because the current implementation is working. Al, am I correct, and can the warning be therefore dropped? CC: Al Viro Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 59c5062..dd71131 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -793,11 +793,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, return(err); } -void hostfs_truncate(struct inode *ino) -{ - not_implemented(); -} - int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) { char *name; @@ -894,7 +889,6 @@ static struct inode_operations hostfs_iops = { .rmdir = hostfs_rmdir, .mknod = hostfs_mknod, .rename = hostfs_rename, - .truncate = hostfs_truncate, .permission = hostfs_permission, .setattr = hostfs_setattr, .getattr = hostfs_getattr, @@ -910,7 +904,6 @@ static struct inode_operations hostfs_dir_iops = { .rmdir = hostfs_rmdir, .mknod = hostfs_mknod, .rename = hostfs_rename, - .truncate = hostfs_truncate, .permission = hostfs_permission, .setattr = hostfs_setattr, .getattr = hostfs_getattr, -- cgit v0.10.2 From dd190d066b7ded8c44b2b67dd0a14bed01525d3c Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 30 Sep 2005 11:59:02 -0700 Subject: [PATCH] fuse: check O_DIRECT Check O_DIRECT and return -EINVAL error in open. dentry_open() also checks this but only after the open method is called. This patch optimizes away the unnecessary upcalls in this case. It could be a correctness issue too: if filesystem has open() with side effect, then it should fail before doing the open, not after. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6454022..657ab11 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -23,6 +23,10 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) struct fuse_file *ff; int err; + /* VFS checks this, but only _after_ ->open() */ + if (file->f_flags & O_DIRECT) + return -EINVAL; + err = generic_file_open(inode, file); if (err) return err; -- cgit v0.10.2 From d38e24e260daf11365efd4ed621235fe9c0ba7ee Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Fri, 30 Sep 2005 11:59:04 -0700 Subject: [PATCH] ioc4_serial: Remove bogus error message This change removes a bogus error message from the IOC4 serial driver interrupt handler. This error message is bogus for two reasons. First, it can never occur given that current code takes care to initialize IOC4 in such a way that these "unknown" interrupts could never occur. Second, this code fails to take into account that other drivers can share the IOC4 interrupt mechanism through SA_SHIRQ, and thus this driver is not in-fact "all-knowing". Finally, this error message triggers every time some "unknown" interrupt occurs -- it's not rate limited or repetition limited in any way, thereby effectively denying use of the console device. Given its bogosity in the first place, it's best to just get rid of it entirely. Acked-by: Pat Gefre Signed-off-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 0c5c96a..f88fdd4 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -973,18 +973,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) this_ir &= ~this_mir; } } - if (this_ir) { - printk(KERN_ERR - "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x," - " sio_ies = 0x%x, other_ir = 0x%x :" - "other_ies = 0x%x\n", - (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" : - "other", this_ir, - readl(&soft->is_ioc4_misc_addr->sio_ir.raw), - readl(&soft->is_ioc4_misc_addr->sio_ies.raw), - readl(&soft->is_ioc4_misc_addr->other_ir.raw), - readl(&soft->is_ioc4_misc_addr->other_ies.raw)); - } } #ifdef DEBUG_INTERRUPTS { -- cgit v0.10.2 From 105d7b38b08f85c9abc3fd31e5cfa7ee4cf0a402 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:04 -0700 Subject: [PATCH] MAINTAINERS: sbp2 driver is not orphaned. Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index f3d9ade..abf7f7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1168,11 +1168,6 @@ L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Orphan -IEEE 1394 SBP2 -L: linux1394-devel@lists.sourceforge.net -W: http://www.linux1394.org/ -S: Orphan - IEEE 1394 SUBSYSTEM P: Ben Collins M: bcollins@debian.org @@ -1207,6 +1202,15 @@ L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained +IEEE 1394 SBP2 +P: Ben Collins +M: bcollins@debian.org +P: Stefan Richter +M: stefanr@s5r6.in-berlin.de +L: linux1394-devel@lists.sourceforge.net +W: http://www.linux1394.org/ +S: Maintained + IMS TWINTURBO FRAMEBUFFER DRIVER P: Paul Mundt M: lethal@chaoticdreams.org -- cgit v0.10.2 From abd559b1052e28d8b9c28aabde241f18fa89090b Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:06 -0700 Subject: [PATCH] sbp2: fix deadlocks and delays on device removal/rmmod Fixes for deadlocks of the ieee1394 and scsi subsystems and long delays in futile error recovery attempts when SBP-2 devices are removed or drivers are unloaded. - Complete commands quickly with DID_NO_CONNECT if the 1394 node is gone or if the 1394 low-level driver was unloaded. - Skip unnecessary work in the eh_abort_handler and eh_device_reset_handler if the node or 1394 low-level driver is gone. - Let scsi's high-level shut down gracefully when sbp2 is being unloaded or detached from the 1394 unit. A call to scsi_remove_device is added for this purpose, which requires us to store a scsi_device pointer. - scsi_device pointer is obtained from slave_alloc hook and cleared by slave_destroy. This avoids usage of the pointer after the scsi device was deleted e.g. by the user via scsi_mod's sysfs interface. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index de88218..5d86b03 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -596,6 +596,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); } +/* + * Is scsi_id valid? Is the 1394 node still present? + */ +static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id) +{ + return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo; +} + /********************************************* @@ -631,11 +639,23 @@ static int sbp2_remove(struct device *dev) { struct unit_directory *ud; struct scsi_id_instance_data *scsi_id; + struct scsi_device *sdev; SBP2_DEBUG("sbp2_remove"); ud = container_of(dev, struct unit_directory, device); scsi_id = ud->device.driver_data; + if (!scsi_id) + return 0; + + /* Trigger shutdown functions in scsi's highlevel. */ + if (scsi_id->scsi_host) + scsi_unblock_requests(scsi_id->scsi_host); + sdev = scsi_id->sdev; + if (sdev) { + scsi_id->sdev = NULL; + scsi_remove_device(sdev); + } sbp2_logout_device(scsi_id); sbp2_remove_device(scsi_id); @@ -2473,37 +2493,26 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, struct scsi_id_instance_data *scsi_id = (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; struct sbp2scsi_host_info *hi; + int result = DID_NO_CONNECT << 16; SBP2_DEBUG("sbp2scsi_queuecommand"); - /* - * If scsi_id is null, it means there is no device in this slot, - * so we should return selection timeout. - */ - if (!scsi_id) { - SCpnt->result = DID_NO_CONNECT << 16; - done (SCpnt); - return 0; - } + if (!sbp2util_node_is_available(scsi_id)) + goto done; hi = scsi_id->hi; if (!hi) { SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); - SCpnt->result = DID_NO_CONNECT << 16; - done (SCpnt); - return(0); + goto done; } /* * Until we handle multiple luns, just return selection time-out * to any IO directed at non-zero LUNs */ - if (SCpnt->device->lun) { - SCpnt->result = DID_NO_CONNECT << 16; - done (SCpnt); - return(0); - } + if (SCpnt->device->lun) + goto done; /* * Check for request sense command, and handle it here @@ -2514,7 +2523,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); - return(0); + return 0; } /* @@ -2522,9 +2531,8 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, */ if (!hpsb_node_entry_valid(scsi_id->ne)) { SBP2_ERR("Bus reset in progress - rejecting command"); - SCpnt->result = DID_BUS_BUSY << 16; - done (SCpnt); - return(0); + result = DID_BUS_BUSY << 16; + goto done; } /* @@ -2535,8 +2543,12 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done); } + return 0; - return(0); +done: + SCpnt->result = result; + done(SCpnt); + return 0; } /* @@ -2683,14 +2695,27 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, } -static int sbp2scsi_slave_configure (struct scsi_device *sdev) +static int sbp2scsi_slave_alloc(struct scsi_device *sdev) { - blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); + ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev; + return 0; +} + +static int sbp2scsi_slave_configure(struct scsi_device *sdev) +{ + blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); return 0; } +static void sbp2scsi_slave_destroy(struct scsi_device *sdev) +{ + ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL; + return; +} + + /* * Called by scsi stack when something has really gone wrong. Usually * called when a command has timed-out for some reason. @@ -2705,7 +2730,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) SBP2_ERR("aborting sbp2 command"); scsi_print_command(SCpnt); - if (scsi_id) { + if (sbp2util_node_is_available(scsi_id)) { /* * Right now, just return any matching command structures @@ -2742,31 +2767,24 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) /* * Called by scsi stack when something has really gone wrong. */ -static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt) +static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) { struct scsi_id_instance_data *scsi_id = (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; + unsigned long flags; SBP2_ERR("reset requested"); - if (scsi_id) { + spin_lock_irqsave(SCpnt->device->host->host_lock, flags); + + if (sbp2util_node_is_available(scsi_id)) { SBP2_ERR("Generating sbp2 fetch agent reset"); sbp2_agent_reset(scsi_id, 0); } - return(SUCCESS); -} - -static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) -{ - unsigned long flags; - int rc; - - spin_lock_irqsave(SCpnt->device->host->host_lock, flags); - rc = __sbp2scsi_reset(SCpnt); spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); - return rc; + return SUCCESS; } static const char *sbp2scsi_info (struct Scsi_Host *host) @@ -2817,7 +2835,9 @@ static struct scsi_host_template scsi_driver_template = { .eh_device_reset_handler = sbp2scsi_reset, .eh_bus_reset_handler = sbp2scsi_reset, .eh_host_reset_handler = sbp2scsi_reset, + .slave_alloc = sbp2scsi_slave_alloc, .slave_configure = sbp2scsi_slave_configure, + .slave_destroy = sbp2scsi_slave_destroy, .this_id = -1, .sg_tablesize = SG_ALL, .use_clustering = ENABLE_CLUSTERING, -- cgit v0.10.2 From 2bab359a5009f330b12a4ed09a57d3d2ac6b3483 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:07 -0700 Subject: [PATCH] sbp2: default to serialize_io=1 Set serialize_io=1 by default. This is safer and required by seemingly more and more hardware. It causes little or no performance loss for S400 devices. Performance of S800 1394b devices may drop by 25...30%. Therefore make the parameter's description and dmesg message clearer about performance impact. Update description of the max_speed parameter too. IEEE1394_SPEED_MAX is currently S800. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5d86b03..12cec7c 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -97,16 +97,18 @@ static char version[] __devinitdata = */ static int max_speed = IEEE1394_SPEED_MAX; module_param(max_speed, int, 0644); -MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)"); +MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)"); /* * Set serialize_io to 1 if you'd like only one scsi command sent * down to us at a time (debugging). This might be necessary for very * badly behaved sbp2 devices. + * + * TODO: Make this configurable per device. */ -static int serialize_io; +static int serialize_io = 1; module_param(serialize_io, int, 0444); -MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)"); +MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)"); /* * Bump up max_sectors if you'd like to support very large sized @@ -2857,7 +2859,8 @@ static int sbp2_module_init(void) /* Module load debug option to force one command at a time (serializing I/O) */ if (serialize_io) { - SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)"); + SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)"); + SBP2_INFO("Try serialize_io=0 for better performance"); scsi_driver_template.can_queue = 1; scsi_driver_template.cmd_per_lun = 1; } -- cgit v0.10.2 From 328699bf0ff4d35a9932ce279441f955e78a890e Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:08 -0700 Subject: [PATCH] ieee1394: reorder activities after bus reset (fixes device detection) Units were not detected if the local IRM performed a bus reset. ("The root node is not cycle master capable; selecting a new root node and resetting...", often seen with iPods and other SBP-2 devices). Rearrange the order of IRM duties and node scanning. TODO: Audit the ROM caching and parsing code for underlying issues. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index b233225..743f13c 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1438,9 +1438,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) if (host->busmgr_id == 0xffff && host->node_count > 1) { u16 root_node = host->node_count - 1; - struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS); - if (ne && ne->busopt.cmc) + /* get cycle master capability flag from root node */ + if (host->is_cycmst || + (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host), + (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)), + &bc, sizeof(quadlet_t)) && + be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT)) hpsb_send_phy_config(host, root_node, -1); else { HPSB_DEBUG("The root node is not cycle master capable; " @@ -1557,24 +1561,19 @@ static int nodemgr_host_thread(void *__hi) } } - if (!nodemgr_check_irm_capability(host, reset_cycles)) { + if (!nodemgr_check_irm_capability(host, reset_cycles) || + !nodemgr_do_irm_duties(host, reset_cycles)) { reset_cycles++; up(&nodemgr_serialize); continue; } + reset_cycles = 0; /* Scan our nodes to get the bus options and create node * entries. This does not do the sysfs stuff, since that * would trigger hotplug callbacks and such, which is a * bad idea at this point. */ nodemgr_node_scan(hi, generation); - if (!nodemgr_do_irm_duties(host, reset_cycles)) { - reset_cycles++; - up(&nodemgr_serialize); - continue; - } - - reset_cycles = 0; /* This actually does the full probe, with sysfs * registration. */ -- cgit v0.10.2 From e31a127c2f99b9cb9abc99a1ec22b75194890800 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:09 -0700 Subject: [PATCH] ieee1394: skip unnecessary pause when scanning config ROMs Skip a superfluous pause that occured when the config ROM of a node was scanned unsuccessfully. This also occurs if a node without link wrongly enables its "link active" self ID flag. A GWCTech 6-port hub does this. Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 743f13c..347ece6 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -64,10 +64,10 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; int i, ret = 0; - for (i = 0; i < 3; i++) { + for (i = 1; ; i++) { ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, buffer, length); - if (!ret) + if (!ret || i == 3) break; if (msleep_interruptible(334)) -- cgit v0.10.2 From db2fd664f8ac3664dfd94d624c0a871bee937bd5 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:09 -0700 Subject: [PATCH] ieee1394: fix for debug output Fix debug code so it prints the correct speed (was defaulting to 100, so anything > 400 showed only 100). Signed-off-by: Stefan Richter Signed-off-by: Ben Collins Signed-off-by: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index d633770..32a1e01 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -70,7 +70,7 @@ const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S32 struct class *hpsb_protocol_class; #ifdef CONFIG_IEEE1394_VERBOSEDEBUG -static void dump_packet(const char *text, quadlet_t *data, int size) +static void dump_packet(const char *text, quadlet_t *data, int size, int speed) { int i; @@ -78,12 +78,15 @@ static void dump_packet(const char *text, quadlet_t *data, int size) size = (size > 4 ? 4 : size); printk(KERN_DEBUG "ieee1394: %s", text); + if (speed > -1 && speed < 6) + printk(" at %s", hpsb_speedto_str[speed]); + printk(":"); for (i = 0; i < size; i++) printk(" %08x", data[i]); printk("\n"); } #else -#define dump_packet(x,y,z) +#define dump_packet(a,b,c,d) #endif static void abort_requests(struct hpsb_host *host); @@ -544,8 +547,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) if (packet->data_size) memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size); - dump_packet("send packet local:", packet->header, - packet->header_size); + dump_packet("send packet local", packet->header, packet->header_size, -1); hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE); hpsb_packet_received(host, data, size, 0); @@ -561,21 +563,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) + NODEID_TO_NODE(packet->node_id)]; } -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - switch (packet->speed_code) { - case 2: - dump_packet("send packet 400:", packet->header, - packet->header_size); - break; - case 1: - dump_packet("send packet 200:", packet->header, - packet->header_size); - break; - default: - dump_packet("send packet 100:", packet->header, - packet->header_size); - } -#endif + dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); return host->driver->transmit_packet(host, packet); } @@ -636,7 +624,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode, if (packet == NULL) { HPSB_DEBUG("unsolicited response packet received - no tlabel match"); - dump_packet("contents:", data, 16); + dump_packet("contents", data, 16, -1); spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); return; } @@ -677,7 +665,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode, if (!tcode_match) { spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); HPSB_INFO("unsolicited response packet received - tcode mismatch"); - dump_packet("contents:", data, 16); + dump_packet("contents", data, 16, -1); return; } @@ -914,7 +902,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, return; } - dump_packet("received packet:", data, size); + dump_packet("received packet", data, size, -1); tcode = (data[0] >> 4) & 0xf; -- cgit v0.10.2 From 63bea35036540c0e8a309aef9bc37a9acfb520ae Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:10 -0700 Subject: [PATCH] ieee1394: use time_before() Use of time_before() macro, defined at linux/jiffies.h, which deal with wrapping correctly and are nicer to read. Signed-off-by: Marcelo Feitoza Parisi Signed-off-by: Domen Puncer Signed-off-by: Ben Collins Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index c502c6e..aeeaeb6 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "csr1212.h" #include "ieee1394.h" @@ -217,7 +218,7 @@ int hpsb_update_config_rom_image(struct hpsb_host *host) /* IEEE 1394a-2000 prohibits using the same generation number * twice in a 60 second period. */ - if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ) + if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ)) /* Wait 60 seconds from the last time this generation number was * used. */ reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies; -- cgit v0.10.2 From 3256cc13983da2cfe45c17788e4f5b379695404e Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:16 -0700 Subject: [PATCH] ieee1394: trivial edits of a few comments trivial edits of a few comments Signed-off-by: Stefan Richter Signed-off-by: Ben Collins Signed-off-by: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index 739e768..38f4211 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -135,17 +135,17 @@ enum isoctl_cmd { enum reset_types { /* 166 microsecond reset -- only type of reset available on - non-1394a capable IEEE 1394 controllers */ + non-1394a capable controllers */ LONG_RESET, /* Short (arbitrated) reset -- only available on 1394a capable - IEEE 1394 capable controllers */ + controllers */ SHORT_RESET, - /* Variants, that set force_root before issueing the bus reset */ + /* Variants that set force_root before issueing the bus reset */ LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT, - /* Variants, that clear force_root before issueing the bus reset */ + /* Variants that clear force_root before issueing the bus reset */ LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT }; -- cgit v0.10.2 From 998150c3d3cf049da7596875f6fdc253db089a9a Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:17 -0700 Subject: [PATCH] ieee1394: remove superfluous include in csr1212 Remove superfluous include. Signed-off-by: Jody McIntyre Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index e673426..28c5f4b 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h @@ -37,7 +37,6 @@ #include #include #include -#include #include #include -- cgit v0.10.2 From 3ae3d0d4ae4131563d9eb55859f4fa5bd39059bd Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:18 -0700 Subject: [PATCH] eth1394: workaround limitation in rawiso routines Work around limitation in rawiso routines. Required with 1394b cards on architectures where PAGE_SIZE is 4096. Based on a previous patch by Ben Collins. Signed-off-by: Jody McIntyre Cc: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index cd53c17..4802bbb 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -89,7 +89,7 @@ #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 1264 $ Ben Collins "; + "$Rev: 1312 $ Ben Collins "; struct fragment_info { struct list_head list; @@ -221,9 +221,7 @@ static int ether1394_open (struct net_device *dev) if (priv->bc_state == ETHER1394_BC_ERROR) { /* we'll try again */ priv->iso = hpsb_iso_recv_init(priv->host, - ETHER1394_GASP_BUFFERS * 2 * - (1 << (priv->host->csr.max_rec + - 1)), + ETHER1394_ISO_BUF_SIZE, ETHER1394_GASP_BUFFERS, priv->broadcast_channel, HPSB_ISO_DMA_PACKET_PER_BUFFER, @@ -635,8 +633,8 @@ static void ether1394_add_host (struct hpsb_host *host) * be checked when the eth device is opened. */ priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; - priv->iso = hpsb_iso_recv_init(host, (ETHER1394_GASP_BUFFERS * 2 * - (1 << (host->csr.max_rec + 1))), + priv->iso = hpsb_iso_recv_init(host, + ETHER1394_ISO_BUF_SIZE, ETHER1394_GASP_BUFFERS, priv->broadcast_channel, HPSB_ISO_DMA_PACKET_PER_BUFFER, @@ -1770,7 +1768,7 @@ fail: static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strcpy (info->driver, driver_name); - strcpy (info->version, "$Rev: 1264 $"); + strcpy (info->version, "$Rev: 1312 $"); /* FIXME XXX provide sane businfo */ strcpy (info->bus_info, "ieee1394"); } diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index ed8f1c4..a77213c 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -44,6 +44,12 @@ #define ETHER1394_GASP_BUFFERS 16 +/* rawiso buffer size - due to a limitation in rawiso, we must limit each + * GASP buffer to be less than PAGE_SIZE. */ +#define ETHER1394_ISO_BUF_SIZE ETHER1394_GASP_BUFFERS * \ + min((unsigned int)PAGE_SIZE, \ + 2 * (1U << (priv->host->csr.max_rec + 1))) + /* Node set == 64 */ #define NODE_SET (ALL_NODES + 1) -- cgit v0.10.2 From f31c9cf3bd6bc1f3e29807ba59d0c7d711385a06 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:18 -0700 Subject: [PATCH] ieee1394: delete legacy module aliases amdtp, dv1394, raw1394, video1394: Delete legacy module aliases. The macros did not work and the aliases are not needed nowadays. Signed-off-by: Stefan Richter Signed-off-by: Ben Collins Signed-off-by: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 84ae027..e8e2856 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -1297,4 +1297,3 @@ static void __exit amdtp_exit_module (void) module_init(amdtp_init_module); module_exit(amdtp_exit_module); -MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16); diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 4538b02..e34730c 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -2660,4 +2660,3 @@ static int __init dv1394_init_module(void) module_init(dv1394_init_module); module_exit(dv1394_exit_module); -MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16); diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index b4fa147..5fe4f2b 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2958,4 +2958,3 @@ static void __exit cleanup_raw1394(void) module_init(init_raw1394); module_exit(cleanup_raw1394); MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 9d6facf..11be9c9 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -1571,4 +1571,3 @@ static int __init video1394_init_module (void) module_init(video1394_init_module); module_exit(video1394_exit_module); -MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16); -- cgit v0.10.2 From 32e7a04faa29f50f65e06d43a9029bb607743e76 Mon Sep 17 00:00:00 2001 From: Jody McIntyre Date: Fri, 30 Sep 2005 11:59:19 -0700 Subject: [PATCH] ohci1394: less noise in dmesg less noise in dmesg Signed-off-by: Ben Collins Signed-off-by: Stefan Richter Signed-off-by: Jody McIntyre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 27018c8..6a6acbd 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) static char version[] __devinitdata = - "$Rev: 1299 $ Ben Collins "; + "$Rev: 1313 $ Ben Collins "; /* Module Parameters */ static int phys_dma = 1; @@ -1084,7 +1084,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); if (printk_ratelimit()) - PRINT(KERN_ERR, "IR legacy activated"); + DBGMSG("IR legacy activated"); } spin_lock_irqsave(&ohci->IR_channel_lock, flags); -- cgit v0.10.2 From 2dd960d66bc12b6b206e63104636514e5da0ddb7 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Fri, 30 Sep 2005 11:59:20 -0700 Subject: [PATCH] utilization of kprobe_mutex is incorrect on x86_64 The up()/down() orders are incorrect in arch/x86_64/kprobes.c file. kprobe_mutext is used to protect the free kprobe instruction slot list. arch_prepare_kprobe applies for a slot from the free list, and arch_remove_kprobe returns a slot to the free list. The incorrect up()/down() orders to operate on kprobe_mutex fail to protect the free list. If 2 threads try to get/return kprobe instruction slot at the same time, the free slot list might be broken, or a free slot might be applied by 2 threads. Signed-off-by: Zhang Yanmin Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index df08c43..76a28b0 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -77,9 +77,9 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn) int __kprobes arch_prepare_kprobe(struct kprobe *p) { /* insn: must be on special executable page on x86_64. */ - up(&kprobe_mutex); - p->ainsn.insn = get_insn_slot(); down(&kprobe_mutex); + p->ainsn.insn = get_insn_slot(); + up(&kprobe_mutex); if (!p->ainsn.insn) { return -ENOMEM; } @@ -231,9 +231,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - up(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); down(&kprobe_mutex); + free_insn_slot(p->ainsn.insn); + up(&kprobe_mutex); } static inline void save_previous_kprobe(void) -- cgit v0.10.2 From e6a045a5b89037ae87c8c1bc84403f1d498e52a1 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Fri, 30 Sep 2005 11:59:21 -0700 Subject: [PATCH] x86_64: fix the BP node_to_cpumask Fix the BP node_to_cpumask. 2.6.14-rc* broke the boot cpu bit as the cpu_to_node(0) is now not setup early enough for numa_init_array. cpu_to_node[] is setup much later at srat_detect_node on acpi srat based em64t machines. This seems like a problem on amd machines too, Tested on em64t though. /sys/devices/system/node/node0/cpumap shows up sanely after this patch. Signed off by: Ravikiran Thirumalai Signed-off-by: Shai Fultheim Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 80a49d9..68ad758 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -178,7 +178,6 @@ void __init numa_init_array(void) rr++; } - set_bit(0, &node_to_cpumask[cpu_to_node(0)]); } #ifdef CONFIG_NUMA_EMU @@ -266,9 +265,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) __cpuinit void numa_add_cpu(int cpu) { - /* BP is initialized elsewhere */ - if (cpu) - set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); + set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); } unsigned long __init numa_free_all_bootmem(void) -- cgit v0.10.2 From 85cc5135ace4c8b75d7b4e1ea9fe15a7fcbd1516 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Fri, 30 Sep 2005 11:59:22 -0700 Subject: [PATCH] x86_64 early numa init fix The tests Alok carried out on Petr's box confirmed that cpu_to_node[BP] is not setup early enough by numa_init_array due to the x86_64 changes in 2.6.14-rc*, and unfortunately set wrongly by the work around code in numa_init_array(). cpu_to_node[0] gets set with 1 early and later gets set properly to 0 during identify_cpu() when all cpus are brought up, but confusing the numa slab in the process. Here is a quick fix for this. The right fix obviously is to have cpu_to_node[bsp] setup early for numa_init_array(). The following patch will fix the problem now, and the code can stay on even when cpu_to_node{BP] gets fixed early correctly. Thanks to Petr for access to his box. Signed off by: Ravikiran Thirumalai Signed-off-by: Alok N Kataria Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 68ad758..2148038 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -167,15 +167,14 @@ void __init numa_init_array(void) mapping. To avoid this fill in the mapping for all possible CPUs, as the number of CPUs is not known yet. We round robin the existing nodes. */ - rr = 0; + rr = first_node(node_online_map); for (i = 0; i < NR_CPUS; i++) { if (cpu_to_node[i] != NUMA_NO_NODE) continue; + cpu_to_node[i] = rr; rr = next_node(rr, node_online_map); if (rr == MAX_NUMNODES) rr = first_node(node_online_map); - cpu_to_node[i] = rr; - rr++; } } -- cgit v0.10.2 From aba7a22f291c13448177b28e0e3d01260ed04fbe Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 30 Sep 2005 13:55:50 -0700 Subject: [IB] mthca: Fix memory leak on device close Remember to free the multicast group context memory table. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index ffbcd40..23a3f56 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -503,6 +503,25 @@ err_free_aux: return err; } +static void mthca_free_icms(struct mthca_dev *mdev) +{ + u8 status; + + mthca_free_icm_table(mdev, mdev->mcg_table.table); + if (mdev->mthca_flags & MTHCA_FLAG_SRQ) + mthca_free_icm_table(mdev, mdev->srq_table.table); + mthca_free_icm_table(mdev, mdev->cq_table.table); + mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); + mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); + mthca_free_icm_table(mdev, mdev->qp_table.qp_table); + mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); + mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); + mthca_unmap_eq_icm(mdev); + + mthca_UNMAP_ICM_AUX(mdev, &status); + mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); +} + static int __devinit mthca_init_arbel(struct mthca_dev *mdev) { struct mthca_dev_lim dev_lim; @@ -580,18 +599,7 @@ static int __devinit mthca_init_arbel(struct mthca_dev *mdev) return 0; err_free_icm: - if (mdev->mthca_flags & MTHCA_FLAG_SRQ) - mthca_free_icm_table(mdev, mdev->srq_table.table); - mthca_free_icm_table(mdev, mdev->cq_table.table); - mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); - mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); - mthca_free_icm_table(mdev, mdev->qp_table.qp_table); - mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); - mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); - mthca_unmap_eq_icm(mdev); - - mthca_UNMAP_ICM_AUX(mdev, &status); - mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); + mthca_free_icms(mdev); err_stop_fw: mthca_UNMAP_FA(mdev, &status); @@ -611,18 +619,7 @@ static void mthca_close_hca(struct mthca_dev *mdev) mthca_CLOSE_HCA(mdev, 0, &status); if (mthca_is_memfree(mdev)) { - if (mdev->mthca_flags & MTHCA_FLAG_SRQ) - mthca_free_icm_table(mdev, mdev->srq_table.table); - mthca_free_icm_table(mdev, mdev->cq_table.table); - mthca_free_icm_table(mdev, mdev->qp_table.rdb_table); - mthca_free_icm_table(mdev, mdev->qp_table.eqp_table); - mthca_free_icm_table(mdev, mdev->qp_table.qp_table); - mthca_free_icm_table(mdev, mdev->mr_table.mpt_table); - mthca_free_icm_table(mdev, mdev->mr_table.mtt_table); - mthca_unmap_eq_icm(mdev); - - mthca_UNMAP_ICM_AUX(mdev, &status); - mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); + mthca_free_icms(mdev); mthca_UNMAP_FA(mdev, &status); mthca_free_icm(mdev, mdev->fw.arbel.fw_icm); -- cgit v0.10.2 From 1c9426e8a59461688bb451e006456987b198e4c0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Sep 2005 14:17:35 -0700 Subject: Linux v2.6.14-rc3 diff --git a/Makefile b/Makefile index 8cf6bec..fdb96bc 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 14 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc3 NAME=Affluent Albatross # *DOCUMENTATION* -- cgit v0.10.2 -- cgit v0.10.2 From a9487e48a34d7ad606f40a76080475a522a27cff Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 1 Oct 2005 09:21:25 +1000 Subject: [PATCH] pmac: fix cpufreq for old tipb 550Mhz The old 550Mhz titanium powerbook can switch to a lower frequency (500Mhz). A user has been repeately reporting overtemp conditions on his machine at high speed so this simple patch adds support to PowerMac cpufreq for this machine. The difference in frequency isn't big but seem enough to fix that user's problems. The patch has been around for some time now and doesn't seem to cause any problem, so I suppose it could go in now. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Alain RICHARD Signed-off-by: Linus Torvalds diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index c060524..d4bc5f6 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -695,6 +695,13 @@ static int __init pmac_cpufreq_setup(void) set_speed_proc = pmu_set_cpu_speed; is_pmu_based = 1; } + /* Else check for TiPb 550 */ + else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { + hi_freq = cur_freq; + low_freq = 500000; + set_speed_proc = pmu_set_cpu_speed; + is_pmu_based = 1; + } /* Else check for TiPb 400 & 500 */ else if (machine_is_compatible("PowerBook3,2")) { /* We only know about the 400 MHz and the 500Mhz model -- cgit v0.10.2 From f0e837d9182d7903bde3ebafbd1d0d68c6d32d43 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 30 Sep 2005 16:54:02 -0700 Subject: [PATCH] r8169: tone down the r8169 driver Tone down the r8169 driver As an alternative, people can use the boot time 'debug' option and/or use 'ethtool -s ethX msglvl xyz'. The different messages are listed at: http://www.zoreil.com/~romieu/r8169/doc/msglvl.txt Signed-off-by: Francois Romieu Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f9223c1..afb3f18 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -92,8 +92,7 @@ VERSION 2.2LK <2005/01/25> #endif /* RTL8169_DEBUG */ #define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \ - NETIF_MSG_IFDOWN) + (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) #define TX_BUFFS_AVAIL(tp) \ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) -- cgit v0.10.2 From 702c96d55059b4a8e5b1eb112ee3b1804708a1bd Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Fri, 30 Sep 2005 16:20:22 -0700 Subject: [PATCH] ARM: Fix IXP2000 serial port resource range. For real this time. Serial port only needs 32 bytes of resource space but we are currently asking for 64K. Signed-off-by: Deepak Saxena [ diff went missing first time due to corrupted patch ] Signed-off-by: Linus Torvalds diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index f34797a..f4d7f1f 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -167,7 +167,7 @@ static struct plat_serial8250_port ixp2000_serial_port[] = { static struct resource ixp2000_uart_resource = { .start = IXP2000_UART_PHYS_BASE, - .end = IXP2000_UART_PHYS_BASE + 0xffff, + .end = IXP2000_UART_PHYS_BASE + 0x1f, .flags = IORESOURCE_MEM, }; -- cgit v0.10.2 From 2d8ab6ad6edf0e8709da9ad24e3f023503f76cee Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Sat, 1 Oct 2005 13:14:17 -0400 Subject: [PATCH] ppc64: fix up()/down() usage for kprobe_mutex The incorrect kprobe_mutex usage on x86_64 had percolated to ppc64 too. First noticed by Yanmin Zhang. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index 7e80d49..9c6facc 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -59,9 +59,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) /* insn must be on a special executable page on ppc64 */ if (!ret) { - up(&kprobe_mutex); - p->ainsn.insn = get_insn_slot(); down(&kprobe_mutex); + p->ainsn.insn = get_insn_slot(); + up(&kprobe_mutex); if (!p->ainsn.insn) ret = -ENOMEM; } @@ -90,9 +90,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { - up(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); down(&kprobe_mutex); + free_insn_slot(p->ainsn.insn); + up(&kprobe_mutex); } static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) -- cgit v0.10.2 From fd2e54b35bd70d11c160ded4834e2378e915356e Mon Sep 17 00:00:00 2001 From: Diego Calleja Date: Sat, 1 Oct 2005 17:00:48 +0200 Subject: [PATCH] trivial #if -> #ifdef Use '#ifdef' consistently on __KERNEL__. This was reported as bug #5340 (isn't easier to send a fix than report the bug?!) Signed-off-by: Diego Calleja Signed-off-by: Linus Torvalds diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 4ed2107..2f0299a 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -183,7 +183,7 @@ struct of_device_id char name[32]; char type[32]; char compatible[128]; -#if __KERNEL__ +#ifdef __KERNEL__ void *data; #else kernel_ulong_t data; -- cgit v0.10.2 From 14bf01bb0599c89fc7f426d20353b76e12555308 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 1 Oct 2005 11:04:18 -0700 Subject: Fix inequality comparison against "task->state" We should always use bitmask ops, rather than depend on some ordering of the different states. With the TASK_NONINTERACTIVE flag, the inequality doesn't really work. Oleg Nesterov argues (likely correctly) that this test is unnecessary in the first place. However, the minimal fix for now is to at least make it work in the presense of TASK_NONINTERACTIVE. Waiting for consensus from Roland & co on potential bigger cleanups. Signed-off-by: Linus Torvalds diff --git a/kernel/exit.c b/kernel/exit.c index ee6d8b8..4307773 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1203,7 +1203,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap, exit_code = p->exit_code; if (unlikely(!exit_code) || - unlikely(p->state > TASK_STOPPED)) + unlikely(p->state & TASK_TRACED)) goto bail_ref; return wait_noreap_copyout(p, pid, uid, why, (exit_code << 8) | 0x7f, -- cgit v0.10.2 From 9f4426dde2be352aabc326539eccc726cea2d98c Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 1 Oct 2005 22:56:34 +0100 Subject: [ARM] 2944/1: GCC 4 mx1ads serial driver compile fix Patch from Vincent Sanders When building the mx1ads ARM platforms the serial driver fails to compile with GCC 4.01 due to extern/static ambiguity. Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4c985e6..4e1e80a 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -860,7 +860,7 @@ imx_console_setup(struct console *co, char *options) return uart_set_options(&sport->port, co, baud, parity, bits, flow); } -extern struct uart_driver imx_reg; +static struct uart_driver imx_reg; static struct console imx_console = { .name = "ttySMX", .write = imx_console_write, -- cgit v0.10.2 From 31f919c3296a30427b18458b13c308513a62c3b9 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 1 Oct 2005 22:56:34 +0100 Subject: [ARM] 2945/1: ARM fortunet fails to build because of missing include Patch from Vincent Sanders When building the fortunet ARM platform it fails to compile because of missing include. Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c index f83a597..3d88da0 100644 --- a/arch/arm/mach-clps711x/fortunet.c +++ b/arch/arm/mach-clps711x/fortunet.c @@ -31,6 +31,8 @@ #include +#include + #include "common.h" struct meminfo memmap = { -- cgit v0.10.2 From 14bfd1ff94f519a59b1e88e682819332d7e98171 Mon Sep 17 00:00:00 2001 From: Sven Henkel Date: Sun, 2 Oct 2005 08:29:18 +1000 Subject: [PATCH] pmac/radeonfb: Add suspend support for M11 chip in new iBook 12" This adds suspend support for the Radeon M11 chip in 12" iBooks manufactured after July 2005. I don't know if the new 14" iBooks also have that chip, so they might also be supported. The chip identifies itself as "RV350 NV" (pci id 0x4e56), revision 0x80. Apple calls it "Snowy", xfree86 names it "ATI FireGL Mobility T2 (M11) NV (AGP)". So, we seem to be lucky here: The suspend-code for the M10 (which also is a "RV350 NV") works flawless for that chip. Signed-off-by: Sven Henkel Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 59a1b6f..097d668 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -62,9 +62,9 @@ static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) OUTPLL(pllSCLK_CNTL, tmp); return; } - /* RV350 (M10) */ + /* RV350 (M10/M11) */ if (rinfo->family == CHIP_FAMILY_RV350) { - /* for RV350/M10, no delays are required. */ + /* for RV350/M10/M11, no delays are required. */ tmp = INPLL(pllSCLK_CNTL2); tmp |= (SCLK_CNTL2__R300_FORCE_TCL | SCLK_CNTL2__R300_FORCE_GA | @@ -248,7 +248,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) return; } - /* M10 */ + /* M10/M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { tmp = INPLL(pllSCLK_CNTL2); tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL | @@ -1155,7 +1155,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) ); OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) ); - /* This is the code for the Aluminium PowerBooks M10 */ + /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { u32 sdram_mode_reg = rinfo->save_regs[35]; static u32 default_mrtable[] = @@ -2741,9 +2741,11 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) rinfo->pm_mode |= radeon_pm_d2; /* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip - * in some desktop G4s), and Via (M9+ chip on iBook G4) + * in some desktop G4s), Via (M9+ chip on iBook G4) and + * Snowy (M11 chip on iBook G4 manufactured after July 2005) */ - if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) { + if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") || + !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) { rinfo->reinit_func = radeon_reinitialize_M10; rinfo->pm_mode |= radeon_pm_off; } -- cgit v0.10.2 From 036bfdcb0dfa39fc1ff5ded196b5fd92f1bb9ea8 Mon Sep 17 00:00:00 2001 From: Sven Henkel Date: Sun, 2 Oct 2005 08:30:33 +1000 Subject: [PATCH] ppc32: Add new iBook 12" to PowerMac models table This adds the new iBook G4 (manufactured after July 2005) to the PowerMac models table. The model name (PowerBook6,7) is taken from a 12" iBook, I don't know if it also matches the 14" version. The patch applies to a vanilla 2.6.13.2 kernel. Signed-off-by: Sven Henkel Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 867336a..dd6d45a 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c @@ -2337,6 +2337,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, }, + { "PowerBook6,7", "iBook G4", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, { "PowerBook6,8", "PowerBook G4 12\"", PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, -- cgit v0.10.2 From 0e3a64e2162f971180bf1fdd91c263dbdfcfd385 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 2 Oct 2005 18:02:25 +0100 Subject: [ARM] Fix EBSA110 network driver link detection EBSA110 link detection didn't read the register - it wrote it. Oops. Signed-off-by: Russell King diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 9b659e3..9f6eb39 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -85,7 +85,7 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg) u_short v; __asm__( "str%?h %1, [%2] @ NAT_RAP\n\t" - "str%?h %0, [%2, #8] @ NET_IDP\n\t" + "ldr%?h %0, [%2, #8] @ NET_IDP\n\t" : "=r" (v) : "r" (reg), "r" (ISAIO_BASE + 0x0464)); return v; -- cgit v0.10.2 From 487fd4eb1445407c9760af08b0b34c3f4cdb4afc Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 2 Oct 2005 18:12:03 +0100 Subject: [ARM] Fix init printk for EBSA110 network driver, and link timer Arrange for the initialisation printks to happen after we've registered the network interface, so we know what name the device is. Also, check the link every 500ms (and use msecs_to_jiffies.) Signed-off-by: Russell King diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 9f6eb39..c56d86d 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -15,16 +15,13 @@ */ #include #include -#include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -33,7 +30,6 @@ #include #include #include -#include #define TX_BUFFERS 15 #define RX_BUFFERS 25 @@ -288,7 +284,7 @@ static void am79c961_timer(unsigned long data) else if (!lnkstat && carrier) netif_carrier_off(dev); - mod_timer(&priv->timer, jiffies + 5*HZ); + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500)); } /* @@ -709,13 +705,9 @@ static int __init am79c961_init(void) goto release; am79c961_banner(); - printk(KERN_INFO "%s: ether address ", dev->name); - /* Retrive and print the ethernet address. */ - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff; - printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); - } spin_lock_init(&priv->chip_lock); init_timer(&priv->timer); @@ -736,8 +728,14 @@ static int __init am79c961_init(void) #endif ret = register_netdev(dev); - if (ret == 0) + if (ret == 0) { + printk(KERN_INFO "%s: ether address ", dev->name); + + for (i = 0; i < 6; i++) + printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); + return 0; + } release: release_region(dev->base_addr, 0x18); -- cgit v0.10.2 From 9e70592fcd87c90e9e98090d66cb79f39d740d4a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 2 Oct 2005 12:59:49 -0500 Subject: [SCSI] fix potential panic with proc on module removal There's a problem in our host release in that it calls scsi_proc_hostdir_rm(). However, if you hold a reference to the host as you remove the module, the host template (which proc uses) will be freed and the system will panic when the host device is finally released. Fix this by moving scsi_proc_hostdir_rm() to where it should be: in scsi_remove_host(). Signed-off-by: James Bottomley diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f2a72d3..02fe371 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -176,6 +176,7 @@ void scsi_remove_host(struct Scsi_Host *shost) transport_unregister_device(&shost->shost_gendev); class_device_unregister(&shost->shost_classdev); device_del(&shost->shost_gendev); + scsi_proc_hostdir_rm(shost->hostt); } EXPORT_SYMBOL(scsi_remove_host); @@ -262,7 +263,6 @@ static void scsi_host_dev_release(struct device *dev) if (shost->work_q) destroy_workqueue(shost->work_q); - scsi_proc_hostdir_rm(shost->hostt); scsi_destroy_command_freelist(shost); kfree(shost->shost_data); -- cgit v0.10.2 From 97af50f60ff1202b0dd9ce481d4cf98c6a578bec Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 2 Oct 2005 15:22:35 -0500 Subject: [SCSI] aic7xxx/aic79xx: fix module removal path not to panic In these drivers, scsi_remove_host() is called too late, at the point it is called, the driver has already shut down too far to accept any I/O that the shutdown might generate. Any generated I/O actually triggers a panic. Fix this by calling scsi_remove_host() as early as possible and not calling scsi_host_put() until just before we kfree the ahc_softc. Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index 70c5fb5..d754b32 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -112,6 +112,9 @@ aic7770_remove(struct device *dev) struct ahc_softc *ahc = dev_get_drvdata(dev); u_long s; + if (ahc->platform_data && ahc->platform_data->host) + scsi_remove_host(ahc->platform_data->host); + ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 6b6d4e2..95c285cc8 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1192,11 +1192,6 @@ ahd_platform_free(struct ahd_softc *ahd) int i, j; if (ahd->platform_data != NULL) { - if (ahd->platform_data->host != NULL) { - scsi_remove_host(ahd->platform_data->host); - scsi_host_put(ahd->platform_data->host); - } - /* destroy all of the device and target objects */ for (i = 0; i < AHD_NUM_TARGETS; i++) { starget = ahd->platform_data->starget[i]; @@ -1226,6 +1221,9 @@ ahd_platform_free(struct ahd_softc *ahd) release_mem_region(ahd->platform_data->mem_busaddr, 0x1000); } + if (ahd->platform_data->host) + scsi_host_put(ahd->platform_data->host); + free(ahd->platform_data, M_DEVBUF); } } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 390b538..bf360ae 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -95,6 +95,9 @@ ahd_linux_pci_dev_remove(struct pci_dev *pdev) struct ahd_softc *ahd = pci_get_drvdata(pdev); u_long s; + if (ahd->platform_data && ahd->platform_data->host) + scsi_remove_host(ahd->platform_data->host); + ahd_lock(ahd, &s); ahd_intr_enable(ahd, FALSE); ahd_unlock(ahd, &s); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 876d1de..6ee1435 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1209,11 +1209,6 @@ ahc_platform_free(struct ahc_softc *ahc) int i, j; if (ahc->platform_data != NULL) { - if (ahc->platform_data->host != NULL) { - scsi_remove_host(ahc->platform_data->host); - scsi_host_put(ahc->platform_data->host); - } - /* destroy all of the device and target objects */ for (i = 0; i < AHC_NUM_TARGETS; i++) { starget = ahc->platform_data->starget[i]; @@ -1242,6 +1237,9 @@ ahc_platform_free(struct ahc_softc *ahc) 0x1000); } + if (ahc->platform_data->host) + scsi_host_put(ahc->platform_data->host); + free(ahc->platform_data, M_DEVBUF); } } diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 3ce77dd..cb30d9c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -143,6 +143,9 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev) struct ahc_softc *ahc = pci_get_drvdata(pdev); u_long s; + if (ahc->platform_data && ahc->platform_data->host) + scsi_remove_host(ahc->platform_data->host); + ahc_lock(ahc, &s); ahc_intr_enable(ahc, FALSE); ahc_unlock(ahc, &s); -- cgit v0.10.2 From d70ddac1bf3a8b102996588010ca87018c3a4a04 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 2 Oct 2005 12:49:52 -0700 Subject: [PATCH] alpha: fix kernel alignment traps Pass in the pointer to the on-stack registers rather than using them directly as the arguments. Ivan noticed that I missed a spot when purging the registers as first stack parameter idiom. Signed-off-by: Linus Torvalds diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 76cc0cb..e38671c 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -196,6 +196,7 @@ entUna: stq $26, 208($sp) stq $27, 216($sp) stq $28, 224($sp) + mov $sp, $19 stq $gp, 232($sp) lda $8, 0x3fff stq $31, 248($sp) diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 6f509a6..f9d1231 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -446,16 +446,15 @@ struct unaligned_stat { /* Macro for exception fixup code to access integer registers. */ -#define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)]) +#define una_reg(r) (regs->regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)]) asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg, - unsigned long a3, unsigned long a4, unsigned long a5, - struct allregs regs) + struct allregs *regs) { long error, tmp1, tmp2, tmp3, tmp4; - unsigned long pc = regs.pc - 4; + unsigned long pc = regs->pc - 4; const struct exception_table_entry *fixup; unaligned[0].count++; @@ -636,7 +635,7 @@ got_exception: printk("Forwarding unaligned exception at %lx (%lx)\n", pc, newpc); - (®s)->pc = newpc; + regs->pc = newpc; return; } @@ -650,7 +649,7 @@ got_exception: current->comm, current->pid); printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", - pc, una_reg(26), regs.ps); + pc, una_reg(26), regs->ps); printk("r0 = %016lx r1 = %016lx r2 = %016lx\n", una_reg(0), una_reg(1), una_reg(2)); printk("r3 = %016lx r4 = %016lx r5 = %016lx\n", @@ -670,10 +669,10 @@ got_exception: una_reg(22), una_reg(23), una_reg(24)); printk("r25= %016lx r27= %016lx r28= %016lx\n", una_reg(25), una_reg(27), una_reg(28)); - printk("gp = %016lx sp = %p\n", regs.gp, ®s+1); + printk("gp = %016lx sp = %p\n", regs->gp, regs+1); dik_show_code((unsigned int *)pc); - dik_show_trace((unsigned long *)(®s+1)); + dik_show_trace((unsigned long *)(regs+1)); if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) { printk("die_if_kernel recursion detected.\n"); -- cgit v0.10.2 From 2c3a0540999ac9bd7147fb98833224a58cdaf217 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Sun, 2 Oct 2005 22:34:35 +0100 Subject: [ARM] 2943/1: Clear the exclusive monitor in v6_early_abort Patch from Catalin Marinas Data abort caused by ldrex/strex can leave the exclusive monitor in an unpredictable state. It is recommended that a clrex/strex is performed to clear this state. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index 8f76f3d..dbd3460 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -20,6 +20,11 @@ */ .align 5 ENTRY(v6_early_abort) +#ifdef CONFIG_CPU_MPCORE + clrex +#else + strex r0, r1, [sp] @ Clear the exclusive monitor +#endif mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR /* -- cgit v0.10.2 From 75f8426c17bc091260a6f7536ba10767596e15eb Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sun, 2 Oct 2005 18:01:42 -0700 Subject: [PATCH] Document from line in patch format Document more details of patch format such as the "from" line and the "---" marker line, and provide more references for patch guidelines. Signed-off-by: Paul Jackson Signed-off-by: Linus Torvalds diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 7f43b04..1d96efe 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -301,8 +301,68 @@ now, but you can do this to mark internal company procedures or just point out some special detail about the sign-off. +12) The canonical patch format -12) More references for submitting patches +The canonical patch subject line is: + + Subject: [PATCH 001/123] [:] + +The canonical patch message body contains the following: + + - A "from" line specifying the patch author. + + - An empty line. + + - The body of the explanation, which will be copied to the + permanent changelog to describe this patch. + + - The "Signed-off-by:" lines, described above, which will + also go in the changelog. + + - A marker line containing simply "---". + + - Any additional comments not suitable for the changelog. + + - The actual patch (diff output). + +The Subject line format makes it very easy to sort the emails +alphabetically by subject line - pretty much any email reader will +support that - since because the sequence number is zero-padded, +the numerical and alphabetic sort is the same. + +See further details on how to phrase the "" in the +"Subject:" line in Andrew Morton's "The perfect patch", referenced +below. + +The "from" line must be the very first line in the message body, +and has the form: + + From: Original Author + +The "from" line specifies who will be credited as the author of the +patch in the permanent changelog. If the "from" line is missing, +then the "From:" line from the email header will be used to determine +the patch author in the changelog. + +The explanation body will be committed to the permanent source +changelog, so should make sense to a competent reader who has long +since forgotten the immediate details of the discussion that might +have led to this patch. + +The "---" marker line serves the essential purpose of marking for patch +handling tools where the changelog message ends. + +One good use for the additional comments after the "---" marker is for +a diffstat, to show what files have changed, and the number of inserted +and deleted lines per file. A diffstat is especially useful on bigger +patches. Other comments relevant only to the moment or the maintainer, +not suitable for the permanent changelog, should also go here. + +See more details on the proper patch format in the following +references. + + +13) More references for submitting patches Andrew Morton, "The perfect patch" (tpp). @@ -310,6 +370,14 @@ Andrew Morton, "The perfect patch" (tpp). Jeff Garzik, "Linux kernel patch submission format." +Greg KH, "How to piss off a kernel subsystem maintainer" + + +Kernel Documentation/CodingStyle + + +Linus Torvald's mail on the canonical patch format: + ----------------------------------- -- cgit v0.10.2 From 51c928c34fa7cff38df584ad01de988805877dba Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 1 Oct 2005 09:38:05 -0500 Subject: [SCSI] Legacy MegaRAID: Fix READ CAPACITY Some Legacy megaraid cards can't actually cope with the scatter/gather version of the READ CAPACITY command (which is what we now send them since altering all SCSI internal I/O to go via the block layer). Fix this (and a few other broken megaraid driver assumptions) by sending the non-sg version of the command if the sg list only has a single element. Signed-off-by: James Bottomley diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 6f308eb..61a6fd8 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -621,8 +621,6 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) if(islogical) { switch (cmd->cmnd[0]) { case TEST_UNIT_READY: - memset(cmd->request_buffer, 0, cmd->request_bufflen); - #if MEGA_HAVE_CLUSTERING /* * Do we support clustering and is the support enabled @@ -652,11 +650,28 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) return NULL; #endif - case MODE_SENSE: + case MODE_SENSE: { + char *buf; + + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *)cmd->request_buffer; + buf = kmap_atomic(sg->page, KM_IRQ0) + + sg->offset; + } else + buf = cmd->request_buffer; memset(cmd->request_buffer, 0, cmd->cmnd[4]); + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *)cmd->request_buffer; + kunmap_atomic(buf - sg->offset, KM_IRQ0); + } cmd->result = (DID_OK << 16); cmd->scsi_done(cmd); return NULL; + } case READ_CAPACITY: case INQUIRY: @@ -1685,14 +1700,23 @@ mega_rundoneq (adapter_t *adapter) static void mega_free_scb(adapter_t *adapter, scb_t *scb) { + unsigned long length; + switch( scb->dma_type ) { case MEGA_DMA_TYPE_NONE: break; case MEGA_BULK_DATA: + if (scb->cmd->use_sg == 0) + length = scb->cmd->request_bufflen; + else { + struct scatterlist *sgl = + (struct scatterlist *)scb->cmd->request_buffer; + length = sgl->length; + } pci_unmap_page(adapter->dev, scb->dma_h_bulkdata, - scb->cmd->request_bufflen, scb->dma_direction); + length, scb->dma_direction); break; case MEGA_SGLIST: @@ -1741,6 +1765,7 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) struct scatterlist *sgl; struct page *page; unsigned long offset; + unsigned int length; Scsi_Cmnd *cmd; int sgcnt; int idx; @@ -1748,14 +1773,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) cmd = scb->cmd; /* Scatter-gather not used */ - if( !cmd->use_sg ) { - - page = virt_to_page(cmd->request_buffer); - offset = offset_in_page(cmd->request_buffer); + if( cmd->use_sg == 0 || (cmd->use_sg == 1 && + !adapter->has_64bit_addr)) { + + if (cmd->use_sg == 0) { + page = virt_to_page(cmd->request_buffer); + offset = offset_in_page(cmd->request_buffer); + length = cmd->request_bufflen; + } else { + sgl = (struct scatterlist *)cmd->request_buffer; + page = sgl->page; + offset = sgl->offset; + length = sgl->length; + } scb->dma_h_bulkdata = pci_map_page(adapter->dev, page, offset, - cmd->request_bufflen, + length, scb->dma_direction); scb->dma_type = MEGA_BULK_DATA; @@ -1765,14 +1799,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) */ if( adapter->has_64bit_addr ) { scb->sgl64[0].address = scb->dma_h_bulkdata; - scb->sgl64[0].length = cmd->request_bufflen; + scb->sgl64[0].length = length; *buf = (u32)scb->sgl_dma_addr; - *len = (u32)cmd->request_bufflen; + *len = (u32)length; return 1; } else { *buf = (u32)scb->dma_h_bulkdata; - *len = (u32)cmd->request_bufflen; + *len = (u32)length; } return 0; } @@ -1791,27 +1825,23 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) if( sgcnt > adapter->sglen ) BUG(); + *len = 0; + for( idx = 0; idx < sgcnt; idx++, sgl++ ) { if( adapter->has_64bit_addr ) { scb->sgl64[idx].address = sg_dma_address(sgl); - scb->sgl64[idx].length = sg_dma_len(sgl); + *len += scb->sgl64[idx].length = sg_dma_len(sgl); } else { scb->sgl[idx].address = sg_dma_address(sgl); - scb->sgl[idx].length = sg_dma_len(sgl); + *len += scb->sgl[idx].length = sg_dma_len(sgl); } } /* Reset pointer and length fields */ *buf = scb->sgl_dma_addr; - /* - * For passthru command, dataxferlen must be set, even for commands - * with a sg list - */ - *len = (u32)cmd->request_bufflen; - /* Return count of SG requests */ return sgcnt; } -- cgit v0.10.2 From d6b9acc0c6c4a7c5d484d15271a5274656d0864f Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Mon, 3 Oct 2005 00:29:10 -0700 Subject: [PATCH] Document patch subject line better Improve explanation of the Subject line fields in Documentation/SubmittingPatches Canonical Patch Format. Signed-off-by: Paul Jackson Signed-off-by: Linus Torvalds diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 1d96efe..237d54c 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -305,7 +305,7 @@ point out some special detail about the sign-off. The canonical patch subject line is: - Subject: [PATCH 001/123] [:] + Subject: [PATCH 001/123] subsystem: summary phrase The canonical patch message body contains the following: @@ -330,9 +330,25 @@ alphabetically by subject line - pretty much any email reader will support that - since because the sequence number is zero-padded, the numerical and alphabetic sort is the same. -See further details on how to phrase the "" in the -"Subject:" line in Andrew Morton's "The perfect patch", referenced -below. +The "subsystem" in the email's Subject should identify which +area or subsystem of the kernel is being patched. + +The "summary phrase" in the email's Subject should concisely +describe the patch which that email contains. The "summary +phrase" should not be a filename. Do not use the same "summary +phrase" for every patch in a whole patch series. + +Bear in mind that the "summary phrase" of your email becomes +a globally-unique identifier for that patch. It propagates +all the way into the git changelog. The "summary phrase" may +later be used in developer discussions which refer to the patch. +People will want to google for the "summary phrase" to read +discussion regarding that patch. + +A couple of example Subjects: + + Subject: [patch 2/5] ext2: improve scalability of bitmap searching + Subject: [PATCHv2 001/207] x86: fix eflags tracking The "from" line must be the very first line in the message body, and has the form: -- cgit v0.10.2 From ddea7be0ec8d1374f0b483a81566ed56ec9f3905 Mon Sep 17 00:00:00 2001 From: Ravikiran G Thirumalai Date: Mon, 3 Oct 2005 10:36:28 -0700 Subject: [PATCH] x86_64: Fix numa node topology detection for srat based x86_64 boxes 2.6.14-rc2 does not assign cpus to proper nodeids on our em64t numa boxen. Our boxes use acpi srat for parsing the numa information. srat_detect_node() used phys_proc_id[] to get to the cpu's local apic id, but phys_proc_id[] represents the cpu<->initial_apic_id mapping. The following patch fixes this problem. Now apicid_to_node[] is properly indexed with the local apic id. Signed-off-by: Ravikiran Thirumalai Acked-by: Suresh Siddha Cc: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 257f5ba..cb28df1 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -967,13 +967,12 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) static void srat_detect_node(void) { #ifdef CONFIG_NUMA - unsigned apicid, node; + unsigned node; int cpu = smp_processor_id(); /* Don't do the funky fallback heuristics the AMD version employs for now. */ - apicid = phys_proc_id[cpu]; - node = apicid_to_node[apicid]; + node = apicid_to_node[hard_smp_processor_id()]; if (node == NUMA_NO_NODE) node = 0; cpu_to_node[cpu] = node; -- cgit v0.10.2 From 325ed8239309cb29f10ea58c5a668058ead11479 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 3 Oct 2005 13:57:23 -0700 Subject: [NET]: Fix packet timestamping. I've found the problem in general. It affects any 64-bit architecture. The problem occurs when you change the system time. Suppose that when you boot your system clock is forward by a day. This gets recorded down in skb_tv_base. You then wind the clock back by a day. From that point onwards the offset will be negative which essentially overflows the 32-bit variables they're stored in. In fact, why don't we just store the real time stamp in those 32-bit variables? After all, we're not going to overflow for quite a while yet. When we do overflow, we'll need a better solution of course. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2741c0c..466c879 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -155,8 +155,6 @@ struct skb_shared_info { #define SKB_DATAREF_SHIFT 16 #define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) -extern struct timeval skb_tv_base; - struct skb_timeval { u32 off_sec; u32 off_usec; @@ -175,7 +173,7 @@ enum { * @prev: Previous buffer in list * @list: List we are on * @sk: Socket we are owned by - * @tstamp: Time we arrived stored as offset to skb_tv_base + * @tstamp: Time we arrived * @dev: Device we arrived on/are leaving by * @input_dev: Device we arrived on * @h: Transport layer header @@ -1255,10 +1253,6 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval * { stamp->tv_sec = skb->tstamp.off_sec; stamp->tv_usec = skb->tstamp.off_usec; - if (skb->tstamp.off_sec) { - stamp->tv_sec += skb_tv_base.tv_sec; - stamp->tv_usec += skb_tv_base.tv_usec; - } } /** @@ -1272,8 +1266,8 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval * */ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp) { - skb->tstamp.off_sec = stamp->tv_sec - skb_tv_base.tv_sec; - skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec; + skb->tstamp.off_sec = stamp->tv_sec; + skb->tstamp.off_usec = stamp->tv_usec; } extern void __net_timestamp(struct sk_buff *skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f80a287..0e9431b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -71,8 +71,6 @@ static kmem_cache_t *skbuff_head_cache __read_mostly; static kmem_cache_t *skbuff_fclone_cache __read_mostly; -struct timeval __read_mostly skb_tv_base; - /* * Keep out-of-line to prevent kernel bloat. * __builtin_return_address is not used because it is not always @@ -1708,8 +1706,6 @@ void __init skb_init(void) NULL, NULL); if (!skbuff_fclone_cache) panic("cannot create skbuff cache"); - - do_gettimeofday(&skb_tv_base); } EXPORT_SYMBOL(___pskb_trim); @@ -1743,4 +1739,3 @@ EXPORT_SYMBOL(skb_prepare_seq_read); EXPORT_SYMBOL(skb_seq_read); EXPORT_SYMBOL(skb_abort_seq_read); EXPORT_SYMBOL(skb_find_text); -EXPORT_SYMBOL(skb_tv_base); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index d54f14d..36339eb 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -240,8 +240,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->packet_id = (unsigned long )entry; pmsg->data_len = data_len; - pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; - pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; + pmsg->timestamp_sec = entry->skb->tstamp.off_sec; + pmsg->timestamp_usec = entry->skb->tstamp.off_usec; pmsg->mark = entry->skb->nfmark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index e2c14f3..2883ccd 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -225,8 +225,8 @@ static void ipt_ulog_packet(unsigned int hooknum, /* copy hook, prefix, timestamp, payload, etc. */ pm->data_len = copy_len; - pm->timestamp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec; - pm->timestamp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec; + pm->timestamp_sec = skb->tstamp.off_sec; + pm->timestamp_usec = skb->tstamp.off_usec; pm->mark = skb->nfmark; pm->hook = hooknum; if (prefix != NULL) diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index aa11cf3..5027bbe 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -238,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) pmsg->packet_id = (unsigned long )entry; pmsg->data_len = data_len; - pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; - pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; + pmsg->timestamp_sec = entry->skb->tstamp.off_sec; + pmsg->timestamp_usec = entry->skb->tstamp.off_usec; pmsg->mark = entry->skb->nfmark; pmsg->hook = entry->info->hook; pmsg->hw_protocol = entry->skb->protocol; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index ff5601c..efcd10f 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -494,8 +494,8 @@ __build_packet_message(struct nfulnl_instance *inst, if (skb->tstamp.off_sec) { struct nfulnl_msg_packet_timestamp ts; - ts.sec = cpu_to_be64(skb_tv_base.tv_sec + skb->tstamp.off_sec); - ts.usec = cpu_to_be64(skb_tv_base.tv_usec + skb->tstamp.off_usec); + ts.sec = cpu_to_be64(skb->tstamp.off_sec); + ts.usec = cpu_to_be64(skb->tstamp.off_usec); NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts); } diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index f81fe8c..eaa44c4 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -492,8 +492,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (entry->skb->tstamp.off_sec) { struct nfqnl_msg_packet_timestamp ts; - ts.sec = cpu_to_be64(skb_tv_base.tv_sec + entry->skb->tstamp.off_sec); - ts.usec = cpu_to_be64(skb_tv_base.tv_usec + entry->skb->tstamp.off_usec); + ts.sec = cpu_to_be64(entry->skb->tstamp.off_sec); + ts.usec = cpu_to_be64(entry->skb->tstamp.off_usec); NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts); } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6a67a87..499ae3d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -654,8 +654,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe __net_timestamp(skb); sock_enable_timestamp(sk); } - h->tp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec; - h->tp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec; + h->tp_sec = skb->tstamp.off_sec; + h->tp_usec = skb->tstamp.off_usec; sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h))); sll->sll_halen = 0; -- cgit v0.10.2 From a232f76732e11c91c2215d3a43cf9ebc7f939939 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 3 Oct 2005 14:01:37 -0700 Subject: [CASSINI]: Convert to ethtool_ops Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 45831fb..2e61742 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -4423,18 +4423,14 @@ static struct { #define CAS_REG_LEN (sizeof(ethtool_register_table)/sizeof(int)) #define CAS_MAX_REGS (sizeof (u32)*CAS_REG_LEN) -static u8 *cas_get_regs(struct cas *cp) +static void cas_read_regs(struct cas *cp, u8 *ptr, int len) { - u8 *ptr = kmalloc(CAS_MAX_REGS, GFP_KERNEL); u8 *p; int i; unsigned long flags; - if (!ptr) - return NULL; - spin_lock_irqsave(&cp->lock, flags); - for (i = 0, p = ptr; i < CAS_REG_LEN ; i ++, p += sizeof(u32)) { + for (i = 0, p = ptr; i < len ; i ++, p += sizeof(u32)) { u16 hval; u32 val; if (ethtool_register_table[i].offsets < 0) { @@ -4447,8 +4443,6 @@ static u8 *cas_get_regs(struct cas *cp) memcpy(p, (u8 *)&val, sizeof(u32)); } spin_unlock_irqrestore(&cp->lock, flags); - - return ptr; } static struct net_device_stats *cas_get_stats(struct net_device *dev) @@ -4561,316 +4555,251 @@ static void cas_set_multicast(struct net_device *dev) spin_unlock_irqrestore(&cp->lock, flags); } -/* Eventually add support for changing the advertisement - * on autoneg. - */ -static int cas_ethtool_ioctl(struct net_device *dev, void __user *ep_user) +static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct cas *cp = netdev_priv(dev); + strncpy(info->driver, DRV_MODULE_NAME, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRV_MODULE_VERSION, ETHTOOL_BUSINFO_LEN); + info->fw_version[0] = '\0'; + strncpy(info->bus_info, pci_name(cp->pdev), ETHTOOL_BUSINFO_LEN); + info->regdump_len = cp->casreg_len < CAS_MAX_REGS ? + cp->casreg_len : CAS_MAX_REGS; + info->n_stats = CAS_NUM_STAT_KEYS; +} + +static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct cas *cp = netdev_priv(dev); u16 bmcr; int full_duplex, speed, pause; - struct ethtool_cmd ecmd; unsigned long flags; enum link_state linkstate = link_up; - if (copy_from_user(&ecmd, ep_user, sizeof(ecmd))) - return -EFAULT; - - switch(ecmd.cmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO }; - - strncpy(info.driver, DRV_MODULE_NAME, - ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRV_MODULE_VERSION, - ETHTOOL_BUSINFO_LEN); - info.fw_version[0] = '\0'; - strncpy(info.bus_info, pci_name(cp->pdev), - ETHTOOL_BUSINFO_LEN); - info.regdump_len = cp->casreg_len < CAS_MAX_REGS ? - cp->casreg_len : CAS_MAX_REGS; - info.n_stats = CAS_NUM_STAT_KEYS; - if (copy_to_user(ep_user, &info, sizeof(info))) - return -EFAULT; - - return 0; + cmd->advertising = 0; + cmd->supported = SUPPORTED_Autoneg; + if (cp->cas_flags & CAS_FLAG_1000MB_CAP) { + cmd->supported |= SUPPORTED_1000baseT_Full; + cmd->advertising |= ADVERTISED_1000baseT_Full; } - case ETHTOOL_GSET: - ecmd.advertising = 0; - ecmd.supported = SUPPORTED_Autoneg; - if (cp->cas_flags & CAS_FLAG_1000MB_CAP) { - ecmd.supported |= SUPPORTED_1000baseT_Full; - ecmd.advertising |= ADVERTISED_1000baseT_Full; + /* Record PHY settings if HW is on. */ + spin_lock_irqsave(&cp->lock, flags); + bmcr = 0; + linkstate = cp->lstate; + if (CAS_PHY_MII(cp->phy_type)) { + cmd->port = PORT_MII; + cmd->transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ? + XCVR_INTERNAL : XCVR_EXTERNAL; + cmd->phy_address = cp->phy_addr; + cmd->advertising |= ADVERTISED_TP | ADVERTISED_MII | + ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full; + + cmd->supported |= + (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_TP | SUPPORTED_MII); + + if (cp->hw_running) { + cas_mif_poll(cp, 0); + bmcr = cas_phy_read(cp, MII_BMCR); + cas_read_mii_link_mode(cp, &full_duplex, + &speed, &pause); + cas_mif_poll(cp, 1); } - /* Record PHY settings if HW is on. */ - spin_lock_irqsave(&cp->lock, flags); - bmcr = 0; - linkstate = cp->lstate; - if (CAS_PHY_MII(cp->phy_type)) { - ecmd.port = PORT_MII; - ecmd.transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ? - XCVR_INTERNAL : XCVR_EXTERNAL; - ecmd.phy_address = cp->phy_addr; - ecmd.advertising |= ADVERTISED_TP | ADVERTISED_MII | - ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full; - - ecmd.supported |= - (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_TP | SUPPORTED_MII); - - if (cp->hw_running) { - cas_mif_poll(cp, 0); - bmcr = cas_phy_read(cp, MII_BMCR); - cas_read_mii_link_mode(cp, &full_duplex, - &speed, &pause); - cas_mif_poll(cp, 1); - } - - } else { - ecmd.port = PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = 0; - ecmd.supported |= SUPPORTED_FIBRE; - ecmd.advertising |= ADVERTISED_FIBRE; - - if (cp->hw_running) { - /* pcs uses the same bits as mii */ - bmcr = readl(cp->regs + REG_PCS_MII_CTRL); - cas_read_pcs_link_mode(cp, &full_duplex, - &speed, &pause); - } + } else { + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + cmd->phy_address = 0; + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_FIBRE; + + if (cp->hw_running) { + /* pcs uses the same bits as mii */ + bmcr = readl(cp->regs + REG_PCS_MII_CTRL); + cas_read_pcs_link_mode(cp, &full_duplex, + &speed, &pause); } - spin_unlock_irqrestore(&cp->lock, flags); + } + spin_unlock_irqrestore(&cp->lock, flags); - if (bmcr & BMCR_ANENABLE) { - ecmd.advertising |= ADVERTISED_Autoneg; - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = ((speed == 10) ? - SPEED_10 : - ((speed == 1000) ? - SPEED_1000 : SPEED_100)); - ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + if (bmcr & BMCR_ANENABLE) { + cmd->advertising |= ADVERTISED_Autoneg; + cmd->autoneg = AUTONEG_ENABLE; + cmd->speed = ((speed == 10) ? + SPEED_10 : + ((speed == 1000) ? + SPEED_1000 : SPEED_100)); + cmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + } else { + cmd->autoneg = AUTONEG_DISABLE; + cmd->speed = + (bmcr & CAS_BMCR_SPEED1000) ? + SPEED_1000 : + ((bmcr & BMCR_SPEED100) ? SPEED_100: + SPEED_10); + cmd->duplex = + (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; + } + if (linkstate != link_up) { + /* Force these to "unknown" if the link is not up and + * autonogotiation in enabled. We can set the link + * speed to 0, but not cmd->duplex, + * because its legal values are 0 and 1. Ethtool will + * print the value reported in parentheses after the + * word "Unknown" for unrecognized values. + * + * If in forced mode, we report the speed and duplex + * settings that we configured. + */ + if (cp->link_cntl & BMCR_ANENABLE) { + cmd->speed = 0; + cmd->duplex = 0xff; } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = - (bmcr & CAS_BMCR_SPEED1000) ? - SPEED_1000 : - ((bmcr & BMCR_SPEED100) ? SPEED_100: - SPEED_10); - ecmd.duplex = - (bmcr & BMCR_FULLDPLX) ? - DUPLEX_FULL : DUPLEX_HALF; - } - if (linkstate != link_up) { - /* Force these to "unknown" if the link is not up and - * autonogotiation in enabled. We can set the link - * speed to 0, but not ecmd.duplex, - * because its legal values are 0 and 1. Ethtool will - * print the value reported in parentheses after the - * word "Unknown" for unrecognized values. - * - * If in forced mode, we report the speed and duplex - * settings that we configured. - */ - if (cp->link_cntl & BMCR_ANENABLE) { - ecmd.speed = 0; - ecmd.duplex = 0xff; - } else { - ecmd.speed = SPEED_10; - if (cp->link_cntl & BMCR_SPEED100) { - ecmd.speed = SPEED_100; - } else if (cp->link_cntl & CAS_BMCR_SPEED1000) { - ecmd.speed = SPEED_1000; - } - ecmd.duplex = (cp->link_cntl & BMCR_FULLDPLX)? - DUPLEX_FULL : DUPLEX_HALF; + cmd->speed = SPEED_10; + if (cp->link_cntl & BMCR_SPEED100) { + cmd->speed = SPEED_100; + } else if (cp->link_cntl & CAS_BMCR_SPEED1000) { + cmd->speed = SPEED_1000; } + cmd->duplex = (cp->link_cntl & BMCR_FULLDPLX)? + DUPLEX_FULL : DUPLEX_HALF; } - if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; + } + return 0; +} - case ETHTOOL_SSET: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; +static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct cas *cp = netdev_priv(dev); + unsigned long flags; - /* Verify the settings we care about. */ - if (ecmd.autoneg != AUTONEG_ENABLE && - ecmd.autoneg != AUTONEG_DISABLE) - return -EINVAL; + /* Verify the settings we care about. */ + if (cmd->autoneg != AUTONEG_ENABLE && + cmd->autoneg != AUTONEG_DISABLE) + return -EINVAL; - if (ecmd.autoneg == AUTONEG_DISABLE && - ((ecmd.speed != SPEED_1000 && - ecmd.speed != SPEED_100 && - ecmd.speed != SPEED_10) || - (ecmd.duplex != DUPLEX_HALF && - ecmd.duplex != DUPLEX_FULL))) - return -EINVAL; + if (cmd->autoneg == AUTONEG_DISABLE && + ((cmd->speed != SPEED_1000 && + cmd->speed != SPEED_100 && + cmd->speed != SPEED_10) || + (cmd->duplex != DUPLEX_HALF && + cmd->duplex != DUPLEX_FULL))) + return -EINVAL; - /* Apply settings and restart link process. */ - spin_lock_irqsave(&cp->lock, flags); - cas_begin_auto_negotiation(cp, &ecmd); - spin_unlock_irqrestore(&cp->lock, flags); - return 0; + /* Apply settings and restart link process. */ + spin_lock_irqsave(&cp->lock, flags); + cas_begin_auto_negotiation(cp, cmd); + spin_unlock_irqrestore(&cp->lock, flags); + return 0; +} - case ETHTOOL_NWAY_RST: - if ((cp->link_cntl & BMCR_ANENABLE) == 0) - return -EINVAL; +static int cas_nway_reset(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + unsigned long flags; - /* Restart link process. */ - spin_lock_irqsave(&cp->lock, flags); - cas_begin_auto_negotiation(cp, NULL); - spin_unlock_irqrestore(&cp->lock, flags); + if ((cp->link_cntl & BMCR_ANENABLE) == 0) + return -EINVAL; - return 0; + /* Restart link process. */ + spin_lock_irqsave(&cp->lock, flags); + cas_begin_auto_negotiation(cp, NULL); + spin_unlock_irqrestore(&cp->lock, flags); - case ETHTOOL_GWOL: - case ETHTOOL_SWOL: - break; /* doesn't exist */ + return 0; +} - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { .cmd = ETHTOOL_GLINK }; +static u32 cas_get_link(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + return cp->lstate == link_up; +} - edata.data = (cp->lstate == link_up); - if (copy_to_user(ep_user, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static u32 cas_get_msglevel(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + return cp->msg_enable; +} - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL }; +static void cas_set_msglevel(struct net_device *dev, u32 value) +{ + struct cas *cp = netdev_priv(dev); + cp->msg_enable = value; +} - edata.data = cp->msg_enable; - if (copy_to_user(ep_user, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int cas_get_regs_len(struct net_device *dev) +{ + struct cas *cp = netdev_priv(dev); + return cp->casreg_len < CAS_MAX_REGS ? cp->casreg_len: CAS_MAX_REGS; +} - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; +static void cas_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct cas *cp = netdev_priv(dev); + regs->version = 0; + /* cas_read_regs handles locks (cp->lock). */ + cas_read_regs(cp, p, regs->len / sizeof(u32)); +} - if (!capable(CAP_NET_ADMIN)) { - return (-EPERM); - } - if (copy_from_user(&edata, ep_user, sizeof(edata))) - return -EFAULT; - cp->msg_enable = edata.data; - return 0; - } +static int cas_get_stats_count(struct net_device *dev) +{ + return CAS_NUM_STAT_KEYS; +} - case ETHTOOL_GREGS: { - struct ethtool_regs edata; - u8 *ptr; - int len = cp->casreg_len < CAS_MAX_REGS ? - cp->casreg_len: CAS_MAX_REGS; - - if (copy_from_user(&edata, ep_user, sizeof (edata))) - return -EFAULT; - - if (edata.len > len) - edata.len = len; - edata.version = 0; - if (copy_to_user (ep_user, &edata, sizeof(edata))) - return -EFAULT; - - /* cas_get_regs handles locks (cp->lock). */ - ptr = cas_get_regs(cp); - if (ptr == NULL) - return -ENOMEM; - if (copy_to_user(ep_user + sizeof (edata), ptr, edata.len)) - return -EFAULT; - - kfree(ptr); - return (0); - } - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings edata; - int len; - - if (copy_from_user(&edata, ep_user, sizeof(edata))) - return -EFAULT; - - len = edata.len; - switch(edata.string_set) { - case ETH_SS_STATS: - edata.len = (len < CAS_NUM_STAT_KEYS) ? - len : CAS_NUM_STAT_KEYS; - if (copy_to_user(ep_user, &edata, sizeof(edata))) - return -EFAULT; - - if (copy_to_user(ep_user + sizeof(edata), - ðtool_cassini_statnames, - (edata.len * ETH_GSTRING_LEN))) - return -EFAULT; - return 0; - default: - return -EINVAL; - } - } - case ETHTOOL_GSTATS: { - int i = 0; - u64 *tmp; - struct ethtool_stats edata; - struct net_device_stats *stats; - int len; - - if (copy_from_user(&edata, ep_user, sizeof(edata))) - return -EFAULT; - - len = edata.n_stats; - stats = cas_get_stats(cp->dev); - edata.cmd = ETHTOOL_GSTATS; - edata.n_stats = (len < CAS_NUM_STAT_KEYS) ? - len : CAS_NUM_STAT_KEYS; - if (copy_to_user(ep_user, &edata, sizeof (edata))) - return -EFAULT; - - tmp = kmalloc(sizeof(u64)*CAS_NUM_STAT_KEYS, GFP_KERNEL); - if (tmp) { - tmp[i++] = stats->collisions; - tmp[i++] = stats->rx_bytes; - tmp[i++] = stats->rx_crc_errors; - tmp[i++] = stats->rx_dropped; - tmp[i++] = stats->rx_errors; - tmp[i++] = stats->rx_fifo_errors; - tmp[i++] = stats->rx_frame_errors; - tmp[i++] = stats->rx_length_errors; - tmp[i++] = stats->rx_over_errors; - tmp[i++] = stats->rx_packets; - tmp[i++] = stats->tx_aborted_errors; - tmp[i++] = stats->tx_bytes; - tmp[i++] = stats->tx_dropped; - tmp[i++] = stats->tx_errors; - tmp[i++] = stats->tx_fifo_errors; - tmp[i++] = stats->tx_packets; - BUG_ON(i != CAS_NUM_STAT_KEYS); - - i = copy_to_user(ep_user + sizeof(edata), - tmp, sizeof(u64)*edata.n_stats); - kfree(tmp); - } else { - return -ENOMEM; - } - if (i) - return -EFAULT; - return 0; - } - } +static void cas_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + memcpy(data, ðtool_cassini_statnames, + CAS_NUM_STAT_KEYS * ETH_GSTRING_LEN); +} - return -EOPNOTSUPP; +static void cas_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *estats, u64 *data) +{ + struct cas *cp = netdev_priv(dev); + struct net_device_stats *stats = cas_get_stats(cp->dev); + int i = 0; + data[i++] = stats->collisions; + data[i++] = stats->rx_bytes; + data[i++] = stats->rx_crc_errors; + data[i++] = stats->rx_dropped; + data[i++] = stats->rx_errors; + data[i++] = stats->rx_fifo_errors; + data[i++] = stats->rx_frame_errors; + data[i++] = stats->rx_length_errors; + data[i++] = stats->rx_over_errors; + data[i++] = stats->rx_packets; + data[i++] = stats->tx_aborted_errors; + data[i++] = stats->tx_bytes; + data[i++] = stats->tx_dropped; + data[i++] = stats->tx_errors; + data[i++] = stats->tx_fifo_errors; + data[i++] = stats->tx_packets; + BUG_ON(i != CAS_NUM_STAT_KEYS); } +static struct ethtool_ops cas_ethtool_ops = { + .get_drvinfo = cas_get_drvinfo, + .get_settings = cas_get_settings, + .set_settings = cas_set_settings, + .nway_reset = cas_nway_reset, + .get_link = cas_get_link, + .get_msglevel = cas_get_msglevel, + .set_msglevel = cas_set_msglevel, + .get_regs_len = cas_get_regs_len, + .get_regs = cas_get_regs, + .get_stats_count = cas_get_stats_count, + .get_strings = cas_get_strings, + .get_ethtool_stats = cas_get_ethtool_stats, +}; + static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct cas *cp = netdev_priv(dev); @@ -4883,10 +4812,6 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) */ down(&cp->pm_sem); switch (cmd) { - case SIOCETHTOOL: - rc = cas_ethtool_ioctl(dev, ifr->ifr_data); - break; - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = cp->phy_addr; /* Fallthrough... */ @@ -5112,6 +5037,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, dev->get_stats = cas_get_stats; dev->set_multicast_list = cas_set_multicast; dev->do_ioctl = cas_ioctl; + dev->ethtool_ops = &cas_ethtool_ops; dev->tx_timeout = cas_tx_timeout; dev->watchdog_timeo = CAS_TX_TIMEOUT; dev->change_mtu = cas_change_mtu; -- cgit v0.10.2 From 399de50bbbb2501a6db43daaa8a2dafbc9bcfe0c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 3 Oct 2005 14:02:39 -0700 Subject: [TG3]: Refine AMD K8 write-reorder chipset test. Test for VIA K8T800 north bridge instead of AMD K8 HyperTransport bridge based on new information from Andi Kleen. The AMD HyperTransport interface is not responsible for PCI transactions and so the re-ordering is more likely done by the VIA north bridge. This code is subject to change if we get more information from AMD or VIA. PCI Express devices are excluded from doing the read flush since all chipsets in the write_reorder list are PCI chipsets. Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 25f85fb..fee0e6e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9284,8 +9284,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) static struct pci_device_id write_reorder_chipsets[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_K8_NB) }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_8385_0) }, { }, }; u32 misc_ctrl_reg; @@ -9300,15 +9300,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_SUN_570X; #endif - /* If we have an AMD 762 or K8 chipset, write - * reordering to the mailbox registers done by the host - * controller can cause major troubles. We read back from - * every mailbox register write to force the writes to be - * posted to the chip in order. - */ - if (pci_dev_present(write_reorder_chipsets)) - tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; - /* Force memory write invalidate off. If we leave it on, * then on 5700_BX chips we have to enable a workaround. * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary @@ -9439,6 +9430,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + /* If we have an AMD 762 or VIA K8T800 chipset, write + * reordering to the mailbox registers done by the host + * controller can cause major troubles. We read back from + * every mailbox register write to force the writes to be + * posted to the chip in order. + */ + if (pci_dev_present(write_reorder_chipsets) && + !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) + tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && tp->pci_lat_timer < 64) { tp->pci_lat_timer = 64; -- cgit v0.10.2 From 81c3d5470ecc70564eb9209946730fe2be93ad06 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 3 Oct 2005 14:13:38 -0700 Subject: [INET]: speedup inet (tcp/dccp) lookups Arnaldo and I agreed it could be applied now, because I have other pending patches depending on this one (Thank you Arnaldo) (The other important patch moves skc_refcnt in a separate cache line, so that the SMP/NUMA performance doesnt suffer from cache line ping pongs) 1) First some performance data : -------------------------------- tcp_v4_rcv() wastes a *lot* of time in __inet_lookup_established() The most time critical code is : sk_for_each(sk, node, &head->chain) { if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ } The sk_for_each() does use prefetch() hints but only the begining of "struct sock" is prefetched. As INET_MATCH first comparison uses inet_sk(__sk)->daddr, wich is far away from the begining of "struct sock", it has to bring into CPU cache cold cache line. Each iteration has to use at least 2 cache lines. This can be problematic if some chains are very long. 2) The goal ----------- The idea I had is to change things so that INET_MATCH() may return FALSE in 99% of cases only using the data already in the CPU cache, using one cache line per iteration. 3) Description of the patch --------------------------- Adds a new 'unsigned int skc_hash' field in 'struct sock_common', filling a 32 bits hole on 64 bits platform. struct sock_common { unsigned short skc_family; volatile unsigned char skc_state; unsigned char skc_reuse; int skc_bound_dev_if; struct hlist_node skc_node; struct hlist_node skc_bind_node; atomic_t skc_refcnt; + unsigned int skc_hash; struct proto *skc_prot; }; Store in this 32 bits field the full hash, not masked by (ehash_size - 1) Using this full hash as the first comparison done in INET_MATCH permits us immediatly skip the element without touching a second cache line in case of a miss. Suppress the sk_hashent/tw_hashent fields since skc_hash (aliased to sk_hash and tw_hash) already contains the slot number if we mask with (ehash_size - 1) File include/net/inet_hashtables.h 64 bits platforms : #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ (((__sk)->sk_hash == (__hash)) ((*((__u64 *)&(inet_sk(__sk)->daddr)))== (__cookie)) && \ ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) 32bits platforms: #define TCP_IPV4_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ (((__sk)->sk_hash == (__hash)) && \ (inet_sk(__sk)->daddr == (__saddr)) && \ (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) - Adds a prefetch(head->chain.first) in __inet_lookup_established()/__tcp_v4_check_established() and __inet6_lookup_established()/__tcp_v6_check_established() and __dccp_v4_check_established() to bring into cache the first element of the list, before the {read|write}_lock(&head->lock); Signed-off-by: Eric Dumazet Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index bb6f88e..e0b9227 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -372,8 +372,9 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk) #define inet_v6_ipv6only(__sk) 0 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ -#define INET6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \ - (((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ +#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && \ + ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ ((__sk)->sk_family == AF_INET6) && \ ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \ ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \ diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h index 081b1ee..e21937c 100644 --- a/include/linux/tc_ematch/tc_em_meta.h +++ b/include/linux/tc_ematch/tc_em_meta.h @@ -71,7 +71,7 @@ enum TCF_META_ID_SK_SNDBUF, TCF_META_ID_SK_ALLOCS, TCF_META_ID_SK_ROUTE_CAPS, - TCF_META_ID_SK_HASHENT, + TCF_META_ID_SK_HASH, TCF_META_ID_SK_LINGERTIME, TCF_META_ID_SK_ACK_BACKLOG, TCF_META_ID_SK_MAX_ACK_BACKLOG, diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 03df3b1..5a2beed 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -26,19 +26,18 @@ struct inet_hashinfo; /* I have no idea if this is a good hash for v6 or not. -DaveM */ -static inline int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport, - const struct in6_addr *faddr, const u16 fport, - const int ehash_size) +static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport, + const struct in6_addr *faddr, const u16 fport) { - int hashent = (lport ^ fport); + unsigned int hashent = (lport ^ fport); hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); hashent ^= hashent >> 16; hashent ^= hashent >> 8; - return (hashent & (ehash_size - 1)); + return hashent; } -static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size) +static inline int inet6_sk_ehashfn(const struct sock *sk) { const struct inet_sock *inet = inet_sk(sk); const struct ipv6_pinfo *np = inet6_sk(sk); @@ -46,7 +45,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size) const struct in6_addr *faddr = &np->daddr; const __u16 lport = inet->num; const __u16 fport = inet->dport; - return inet6_ehashfn(laddr, lport, faddr, fport, ehash_size); + return inet6_ehashfn(laddr, lport, faddr, fport); } /* @@ -69,14 +68,14 @@ static inline struct sock * /* Optimize here for direct hit, only listening connections can * have wildcards anyways. */ - const int hash = inet6_ehashfn(daddr, hnum, saddr, sport, - hashinfo->ehash_size); - struct inet_ehash_bucket *head = &hashinfo->ehash[hash]; + unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport); + struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); + prefetch(head->chain.first); read_lock(&head->lock); sk_for_each(sk, node, &head->chain) { /* For IPV6 do the cheaper port and family tests first. */ - if (INET6_MATCH(sk, saddr, daddr, ports, dif)) + if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ } /* Must check for a TIME_WAIT'er before going to listener hash. */ diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 646b6ea..35f49e6 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -108,7 +108,7 @@ struct inet_hashinfo { struct inet_bind_hashbucket *bhash; int bhash_size; - int ehash_size; + unsigned int ehash_size; /* All sockets in TCP_LISTEN state will be in here. This is the only * table where wildcard'd TCP sockets can exist. Hash function here @@ -130,17 +130,16 @@ struct inet_hashinfo { int port_rover; }; -static inline int inet_ehashfn(const __u32 laddr, const __u16 lport, - const __u32 faddr, const __u16 fport, - const int ehash_size) +static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport, + const __u32 faddr, const __u16 fport) { - int h = (laddr ^ lport) ^ (faddr ^ fport); + unsigned int h = (laddr ^ lport) ^ (faddr ^ fport); h ^= h >> 16; h ^= h >> 8; - return h & (ehash_size - 1); + return h; } -static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size) +static inline int inet_sk_ehashfn(const struct sock *sk) { const struct inet_sock *inet = inet_sk(sk); const __u32 laddr = inet->rcv_saddr; @@ -148,7 +147,14 @@ static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size) const __u32 faddr = inet->daddr; const __u16 fport = inet->dport; - return inet_ehashfn(laddr, lport, faddr, fport, ehash_size); + return inet_ehashfn(laddr, lport, faddr, fport); +} + +static inline struct inet_ehash_bucket *inet_ehash_bucket( + struct inet_hashinfo *hashinfo, + unsigned int hash) +{ + return &hashinfo->ehash[hash & (hashinfo->ehash_size - 1)]; } extern struct inet_bind_bucket * @@ -235,9 +241,11 @@ static inline void __inet_hash(struct inet_hashinfo *hashinfo, lock = &hashinfo->lhash_lock; inet_listen_wlock(hashinfo); } else { - sk->sk_hashent = inet_sk_ehashfn(sk, hashinfo->ehash_size); - list = &hashinfo->ehash[sk->sk_hashent].chain; - lock = &hashinfo->ehash[sk->sk_hashent].lock; + struct inet_ehash_bucket *head; + sk->sk_hash = inet_sk_ehashfn(sk); + head = inet_ehash_bucket(hashinfo, sk->sk_hash); + list = &head->chain; + lock = &head->lock; write_lock(lock); } __sk_add_node(sk, list); @@ -268,9 +276,8 @@ static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk) inet_listen_wlock(hashinfo); lock = &hashinfo->lhash_lock; } else { - struct inet_ehash_bucket *head = &hashinfo->ehash[sk->sk_hashent]; - lock = &head->lock; - write_lock_bh(&head->lock); + lock = &inet_ehash_bucket(hashinfo, sk->sk_hash)->lock; + write_lock_bh(lock); } if (__sk_del_node_init(sk)) @@ -337,23 +344,27 @@ sherry_cache: #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr)); #endif /* __BIG_ENDIAN */ -#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\ - (((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ +#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && \ + ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\ - (((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ +#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ + (((__sk)->sk_hash == (__hash)) && \ + ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) #else /* 32-bit arch */ #define INET_ADDR_COOKIE(__name, __saddr, __daddr) -#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \ - ((inet_sk(__sk)->daddr == (__saddr)) && \ +#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif) \ + (((__sk)->sk_hash == (__hash)) && \ + (inet_sk(__sk)->daddr == (__saddr)) && \ (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) -#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif) \ - ((inet_twsk(__sk)->tw_daddr == (__saddr)) && \ +#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ + (((__sk)->sk_hash == (__hash)) && \ + (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) @@ -378,18 +389,19 @@ static inline struct sock * /* Optimize here for direct hit, only listening connections can * have wildcards anyways. */ - const int hash = inet_ehashfn(daddr, hnum, saddr, sport, hashinfo->ehash_size); - struct inet_ehash_bucket *head = &hashinfo->ehash[hash]; + unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport); + struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); + prefetch(head->chain.first); read_lock(&head->lock); sk_for_each(sk, node, &head->chain) { - if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif)) + if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ } /* Must check for a TIME_WAIT'er before going to listener hash. */ sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { - if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif)) + if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) goto hit; } sk = NULL; diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 3b07035..4ade56e 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -112,6 +112,7 @@ struct inet_timewait_sock { #define tw_node __tw_common.skc_node #define tw_bind_node __tw_common.skc_bind_node #define tw_refcnt __tw_common.skc_refcnt +#define tw_hash __tw_common.skc_hash #define tw_prot __tw_common.skc_prot volatile unsigned char tw_substate; /* 3 bits hole, try to pack */ @@ -126,7 +127,6 @@ struct inet_timewait_sock { /* And these are ours. */ __u8 tw_ipv6only:1; /* 31 bits hole, try to pack */ - int tw_hashent; int tw_timeout; unsigned long tw_ttd; struct inet_bind_bucket *tw_tb; diff --git a/include/net/sock.h b/include/net/sock.h index 8c48fbe..b644080 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -99,6 +99,7 @@ struct proto; * @skc_node: main hash linkage for various protocol lookup tables * @skc_bind_node: bind hash linkage for various protocol lookup tables * @skc_refcnt: reference count + * @skc_hash: hash value used with various protocol lookup tables * @skc_prot: protocol handlers inside a network family * * This is the minimal network layer representation of sockets, the header @@ -112,6 +113,7 @@ struct sock_common { struct hlist_node skc_node; struct hlist_node skc_bind_node; atomic_t skc_refcnt; + unsigned int skc_hash; struct proto *skc_prot; }; @@ -139,7 +141,6 @@ struct sock_common { * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) * @sk_lingertime: %SO_LINGER l_linger setting - * @sk_hashent: hash entry in several tables (e.g. inet_hashinfo.ehash) * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct * @sk_error_queue: rarely used @@ -186,6 +187,7 @@ struct sock { #define sk_node __sk_common.skc_node #define sk_bind_node __sk_common.skc_bind_node #define sk_refcnt __sk_common.skc_refcnt +#define sk_hash __sk_common.skc_hash #define sk_prot __sk_common.skc_prot unsigned char sk_shutdown : 2, sk_no_check : 2, @@ -208,7 +210,6 @@ struct sock { unsigned int sk_allocation; int sk_sndbuf; int sk_route_caps; - int sk_hashent; unsigned long sk_flags; unsigned long sk_lingertime; /* diff --git a/net/atm/common.c b/net/atm/common.c index 801a581..63feea4 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -46,7 +46,7 @@ static void __vcc_insert_socket(struct sock *sk) struct atm_vcc *vcc = atm_sk(sk); struct hlist_head *head = &vcc_hash[vcc->vci & (VCC_HTABLE_SIZE - 1)]; - sk->sk_hashent = vcc->vci & (VCC_HTABLE_SIZE - 1); + sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); sk_add_node(sk, head); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 40fe6af..ae088d1 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -62,27 +62,27 @@ static int __dccp_v4_check_established(struct sock *sk, const __u16 lport, const int dif = sk->sk_bound_dev_if; INET_ADDR_COOKIE(acookie, saddr, daddr) const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport); - const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, - dccp_hashinfo.ehash_size); - struct inet_ehash_bucket *head = &dccp_hashinfo.ehash[hash]; + unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport); + struct inet_ehash_bucket *head = inet_ehash_bucket(&dccp_hashinfo, hash); const struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; + prefetch(head->chain.first); write_lock(&head->lock); /* Check TIME-WAIT sockets first. */ sk_for_each(sk2, node, &(head + dccp_hashinfo.ehash_size)->chain) { tw = inet_twsk(sk2); - if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) + if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) goto not_unique; } tw = NULL; /* And established part... */ sk_for_each(sk2, node, &head->chain) { - if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif)) + if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) goto not_unique; } @@ -90,7 +90,7 @@ static int __dccp_v4_check_established(struct sock *sk, const __u16 lport, * in hash table socket with a funny identity. */ inet->num = lport; inet->sport = htons(lport); - sk->sk_hashent = hash; + sk->sk_hash = hash; BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); sock_prot_inc_use(sk->sk_prot); diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 4d1502a..f9076ef 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -20,7 +20,7 @@ void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashi struct inet_bind_hashbucket *bhead; struct inet_bind_bucket *tb; /* Unlink from established hashes. */ - struct inet_ehash_bucket *ehead = &hashinfo->ehash[tw->tw_hashent]; + struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash); write_lock(&ehead->lock); if (hlist_unhashed(&tw->tw_node)) { @@ -60,7 +60,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, { const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); - struct inet_ehash_bucket *ehead = &hashinfo->ehash[sk->sk_hashent]; + struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash); struct inet_bind_hashbucket *bhead; /* Step 1: Put TW into bind hash. Original socket stays there too. Note, that any socket with inet->num != 0 MUST be bound in @@ -106,7 +106,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_dport = inet->dport; tw->tw_family = sk->sk_family; tw->tw_reuse = sk->sk_reuse; - tw->tw_hashent = sk->sk_hashent; + tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; tw->tw_prot = sk->sk_prot_creator; atomic_set(&tw->tw_refcnt, 1); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 13dfb39..c85819d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -130,19 +130,20 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, int dif = sk->sk_bound_dev_if; INET_ADDR_COOKIE(acookie, saddr, daddr) const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport); - const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, tcp_hashinfo.ehash_size); - struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; + unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport); + struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash); struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; + prefetch(head->chain.first); write_lock(&head->lock); /* Check TIME-WAIT sockets first. */ sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) { tw = inet_twsk(sk2); - if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) { + if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) { const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2); struct tcp_sock *tp = tcp_sk(sk); @@ -179,7 +180,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport, /* And established part... */ sk_for_each(sk2, node, &head->chain) { - if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif)) + if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) goto not_unique; } @@ -188,7 +189,7 @@ unique: * in hash table socket with a funny identity. */ inet->num = lport; inet->sport = htons(lport); - sk->sk_hashent = hash; + sk->sk_hash = hash; BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); sock_prot_inc_use(sk->sk_prot); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 80643e6..d693cb9 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -209,9 +209,11 @@ static __inline__ void __tcp_v6_hash(struct sock *sk) lock = &tcp_hashinfo.lhash_lock; inet_listen_wlock(&tcp_hashinfo); } else { - sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size); - list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; - lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; + unsigned int hash; + sk->sk_hash = hash = inet6_sk_ehashfn(sk); + hash &= (tcp_hashinfo.ehash_size - 1); + list = &tcp_hashinfo.ehash[hash].chain; + lock = &tcp_hashinfo.ehash[hash].lock; write_lock(lock); } @@ -322,13 +324,13 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, const struct in6_addr *saddr = &np->daddr; const int dif = sk->sk_bound_dev_if; const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); - const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport, - tcp_hashinfo.ehash_size); - struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; + unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport); + struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash); struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; + prefetch(head->chain.first); write_lock(&head->lock); /* Check TIME-WAIT sockets first. */ @@ -365,14 +367,14 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, /* And established part... */ sk_for_each(sk2, node, &head->chain) { - if (INET6_MATCH(sk2, saddr, daddr, ports, dif)) + if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif)) goto not_unique; } unique: BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); - sk->sk_hashent = hash; + sk->sk_hash = hash; sock_prot_inc_use(sk->sk_prot); write_unlock(&head->lock); diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 00eae5f..cf68a59 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -393,10 +393,10 @@ META_COLLECTOR(int_sk_route_caps) dst->value = skb->sk->sk_route_caps; } -META_COLLECTOR(int_sk_hashent) +META_COLLECTOR(int_sk_hash) { SKIP_NONLOCAL(skb); - dst->value = skb->sk->sk_hashent; + dst->value = skb->sk->sk_hash; } META_COLLECTOR(int_sk_lingertime) @@ -515,7 +515,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = { [META_ID(SK_FORWARD_ALLOCS)] = META_FUNC(int_sk_fwd_alloc), [META_ID(SK_ALLOCS)] = META_FUNC(int_sk_alloc), [META_ID(SK_ROUTE_CAPS)] = META_FUNC(int_sk_route_caps), - [META_ID(SK_HASHENT)] = META_FUNC(int_sk_hashent), + [META_ID(SK_HASH)] = META_FUNC(int_sk_hash), [META_ID(SK_LINGERTIME)] = META_FUNC(int_sk_lingertime), [META_ID(SK_ACK_BACKLOG)] = META_FUNC(int_sk_ack_bl), [META_ID(SK_MAX_ACK_BACKLOG)] = META_FUNC(int_sk_max_ack_bl), -- cgit v0.10.2 From 496a22b08fa326bf17c11eb900e0505aa9da3506 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 3 Oct 2005 14:16:34 -0700 Subject: [NET]: Fix "sysctl_net.c:36: error: 'core_table' undeclared here" During the build for ARM machine type "fortunet", this error occurred: CC net/sysctl_net.o net/sysctl_net.c:36: error: 'core_table' undeclared here (not in a function) It appears that the following configuration settings cause this error due to a missing include: CONFIG_SYSCTL=y CONFIG_NET=y # CONFIG_INET is not set core_table appears to be declared in net/sock.h. if CONFIG_INET were defined, net/sock.h would have been included via: sysctl_net.c -> net/ip.h -> linux/ip.h -> net/sock.h so include it directly. Signed-off-by: Russell King Signed-off-by: David S. Miller diff --git a/net/sysctl_net.c b/net/sysctl_net.c index c5241fc..55538f6 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -16,6 +16,8 @@ #include #include +#include + #ifdef CONFIG_INET #include #endif -- cgit v0.10.2 From 444fc8fc3a1f926fa224655b8950bd853368c1a3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 3 Oct 2005 14:18:10 -0700 Subject: [IPV4]: Fix "Proxy ARP seems broken" Meelis Roos wrote: > RK> My firewall setup relies on proxyarp working. However, with 2.6.14-rc3, > RK> it appears to be completely broken. The firewall is 212.18.232.186, > > Same here with some kernel between 14-rc2 and 14-rc3 - no reposnse to > ARP on a proxyarp gateway. Sorry, no exact revison and no more debugging > yet since it'a a production gateway. The breakage is caused by the change to use the CB area for flagging whether a packet has been queued due to proxy_delay. This area gets cleared every time arp_rcv gets called. Unfortunately packets delayed due to proxy_delay also go through arp_rcv when they are reprocessed. In fact, I can't think of a reason why delayed proxy packets should go through netfilter again at all. So the easiest solution is to bypass that and go straight to arp_process. This is essentially what would've happened before netfilter support was added to ARP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8bf312b..ec0e368 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -697,12 +697,6 @@ void arp_send(int type, int ptype, u32 dest_ip, arp_xmit(skb); } -static void parp_redo(struct sk_buff *skb) -{ - nf_reset(skb); - arp_rcv(skb, skb->dev, NULL, skb->dev); -} - /* * Process an arp request. */ @@ -922,6 +916,11 @@ out: return 0; } +static void parp_redo(struct sk_buff *skb) +{ + arp_process(skb); +} + /* * Receive an arp request from the device layer. -- cgit v0.10.2 From f36d6ab182a5c68e92ea3e85821dde9d29bfe284 Mon Sep 17 00:00:00 2001 From: Yan Zheng Date: Mon, 3 Oct 2005 14:19:15 -0700 Subject: [IPV6]: Fix ipv6 fragment ID selection at slow path Signed-Off-By: Yan Zheng Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 2f589f2..563b442 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -666,7 +666,7 @@ slow_path: */ fh->nexthdr = nexthdr; fh->reserved = 0; - if (frag_id) { + if (!frag_id) { ipv6_select_ident(skb, fh); frag_id = fh->identification; } else -- cgit v0.10.2 From a5e7c210fefd2454c757a3542e41063407ca7108 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Oct 2005 14:21:58 -0700 Subject: [IPV6]: Fix leak added by udp connect dst caching fix. Based upon a patch from Mitsuru KANDA Signed-off-by: David S. Miller diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 6001948..e4cad11 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -852,10 +852,16 @@ do_append_data: else if (!corkreq) err = udp_v6_push_pending_frames(sk, up); - if (dst && connected) - ip6_dst_store(sk, dst, - ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? - &np->daddr : NULL); + if (dst) { + if (connected) { + ip6_dst_store(sk, dst, + ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? + &np->daddr : NULL); + } else { + dst_release(dst); + } + } + if (err > 0) err = np->recverr ? net_xmit_errno(err) : 0; release_sock(sk); -- cgit v0.10.2 From e5ed639913eea3e4783a550291775ab78dd84966 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 3 Oct 2005 14:35:55 -0700 Subject: [IPV4]: Replace __in_dev_get with __in_dev_get_rcu/rtnl The following patch renames __in_dev_get() to __in_dev_get_rtnl() and introduces __in_dev_get_rcu() to cover the second case. 1) RCU with refcnt should use in_dev_get(). 2) RCU without refcnt should use __in_dev_get_rcu(). 3) All others must hold RTNL and use __in_dev_get_rtnl(). There is one exception in net/ipv4/route.c which is in fact a pre-existing race condition. I've marked it as such so that we remember to fix it. This patch is based on suggestions and prior work by Suzanne Wood and Paul McKenney. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6d00c3d..bf81cd45 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2776,7 +2776,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev) return 0; rcu_read_lock(); - idev = __in_dev_get(dev); + idev = __in_dev_get_rcu(dev); if (!idev) goto out; diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c index 74e151a..7a8b22a 100644 --- a/drivers/net/wan/sdlamain.c +++ b/drivers/net/wan/sdlamain.c @@ -57,6 +57,7 @@ #include /* request_region(), release_region() */ #include /* WAN router definitions */ #include /* WANPIPE common user API definitions */ +#include #include #include /* phys_to_virt() */ @@ -1268,37 +1269,41 @@ unsigned long get_ip_address(struct net_device *dev, int option) struct in_ifaddr *ifaddr; struct in_device *in_dev; + unsigned long addr = 0; - if ((in_dev = __in_dev_get(dev)) == NULL){ - return 0; + rcu_read_lock(); + if ((in_dev = __in_dev_get_rcu(dev)) == NULL){ + goto out; } if ((ifaddr = in_dev->ifa_list)== NULL ){ - return 0; + goto out; } switch (option){ case WAN_LOCAL_IP: - return ifaddr->ifa_local; + addr = ifaddr->ifa_local; break; case WAN_POINTOPOINT_IP: - return ifaddr->ifa_address; + addr = ifaddr->ifa_address; break; case WAN_NETMASK_IP: - return ifaddr->ifa_mask; + addr = ifaddr->ifa_mask; break; case WAN_BROADCAST_IP: - return ifaddr->ifa_broadcast; + addr = ifaddr->ifa_broadcast; break; default: - return 0; + break; } - return 0; +out: + rcu_read_unlock(); + return addr; } void add_gateway(sdla_t *card, struct net_device *dev) diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index b56a7b5..a6d3b55 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -769,7 +769,7 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ #ifdef CONFIG_INET rcu_read_lock(); - if ((in_dev = __in_dev_get(dev)) != NULL) + if ((in_dev = __in_dev_get_rcu(dev)) != NULL) { for (ifa=in_dev->ifa_list; ifa != NULL; ifa=ifa->ifa_next) { diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 4b0acae..7bc7fc8 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -1352,7 +1352,7 @@ static unsigned char *strip_make_packet(unsigned char *buffer, struct in_device *in_dev; rcu_read_lock(); - in_dev = __in_dev_get(strip_info->dev); + in_dev = __in_dev_get_rcu(strip_info->dev); if (in_dev == NULL) { rcu_read_unlock(); return NULL; @@ -1508,7 +1508,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb) brd = addr = 0; rcu_read_lock(); - in_dev = __in_dev_get(strip_info->dev); + in_dev = __in_dev_get_rcu(strip_info->dev); if (in_dev) { if (in_dev->ifa_list) { brd = in_dev->ifa_list->ifa_broadcast; diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index e90fb72..2869022 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -358,9 +359,10 @@ static __inline__ int led_get_net_activity(void) /* we are running as tasklet, so locking dev_base * for reading should be OK */ read_lock(&dev_base_lock); + rcu_read_lock(); for (dev = dev_base; dev; dev = dev->next) { struct net_device_stats *stats; - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rcu(dev); if (!in_dev || !in_dev->ifa_list) continue; if (LOOPBACK(in_dev->ifa_list->ifa_local)) @@ -371,6 +373,7 @@ static __inline__ int led_get_net_activity(void) rx_total += stats->rx_packets; tx_total += stats->tx_packets; } + rcu_read_unlock(); read_unlock(&dev_base_lock); retval = 0; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 86582cf..71de834 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -5200,7 +5200,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) if (!card->vlangrp) return; rcu_read_lock(); - in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]); + in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); if (!in_dev) goto out; for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { @@ -7725,7 +7725,7 @@ qeth_arp_constructor(struct neighbour *neigh) goto out; rcu_read_lock(); - in_dev = rcu_dereference(__in_dev_get(dev)); + in_dev = __in_dev_get_rcu(dev); if (in_dev == NULL) { rcu_read_unlock(); return -EINVAL; diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 7e1e15f..fd7af86 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -142,13 +142,21 @@ static __inline__ int bad_mask(u32 mask, u32 addr) #define endfor_ifa(in_dev) } +static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev) +{ + struct in_device *in_dev = dev->ip_ptr; + if (in_dev) + in_dev = rcu_dereference(in_dev); + return in_dev; +} + static __inline__ struct in_device * in_dev_get(const struct net_device *dev) { struct in_device *in_dev; rcu_read_lock(); - in_dev = dev->ip_ptr; + in_dev = __in_dev_get_rcu(dev); if (in_dev) atomic_inc(&in_dev->refcnt); rcu_read_unlock(); @@ -156,7 +164,7 @@ in_dev_get(const struct net_device *dev) } static __inline__ struct in_device * -__in_dev_get(const struct net_device *dev) +__in_dev_get_rtnl(const struct net_device *dev) { return (struct in_device*)dev->ip_ptr; } diff --git a/net/atm/clip.c b/net/atm/clip.c index 28dab55..4f54c9a 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -310,7 +310,7 @@ static int clip_constructor(struct neighbour *neigh) if (neigh->type != RTN_UNICAST) return -EINVAL; rcu_read_lock(); - in_dev = rcu_dereference(__in_dev_get(dev)); + in_dev = __in_dev_get_rcu(dev); if (!in_dev) { rcu_read_unlock(); return -EINVAL; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 5265dfd..802fe11 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -703,7 +703,7 @@ int netpoll_setup(struct netpoll *np) if (!np->local_ip) { rcu_read_lock(); - in_dev = __in_dev_get(ndev); + in_dev = __in_dev_get_rcu(ndev); if (!in_dev || !in_dev->ifa_list) { rcu_read_unlock(); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b7f2d65..44de070 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1667,7 +1667,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) struct in_device *in_dev; rcu_read_lock(); - in_dev = __in_dev_get(pkt_dev->odev); + in_dev = __in_dev_get_rcu(pkt_dev->odev); if (in_dev) { if (in_dev->ifa_list) { pkt_dev->saddr_min = in_dev->ifa_list->ifa_address; diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 4a62093..34fdac5 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -406,7 +406,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, unsigned long network = 0; rcu_read_lock(); - idev = __in_dev_get(dev); + idev = __in_dev_get_rcu(dev); if (idev) { if (idev->ifa_list) network = ntohl(idev->ifa_list->ifa_address) & diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index ec0e368..b425748 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -241,7 +241,7 @@ static int arp_constructor(struct neighbour *neigh) neigh->type = inet_addr_type(addr); rcu_read_lock(); - in_dev = rcu_dereference(__in_dev_get(dev)); + in_dev = __in_dev_get_rcu(dev); if (in_dev == NULL) { rcu_read_unlock(); return -EINVAL; @@ -989,8 +989,8 @@ static int arp_req_set(struct arpreq *r, struct net_device * dev) ipv4_devconf.proxy_arp = 1; return 0; } - if (__in_dev_get(dev)) { - __in_dev_get(dev)->cnf.proxy_arp = 1; + if (__in_dev_get_rtnl(dev)) { + __in_dev_get_rtnl(dev)->cnf.proxy_arp = 1; return 0; } return -ENXIO; @@ -1095,8 +1095,8 @@ static int arp_req_delete(struct arpreq *r, struct net_device * dev) ipv4_devconf.proxy_arp = 0; return 0; } - if (__in_dev_get(dev)) { - __in_dev_get(dev)->cnf.proxy_arp = 0; + if (__in_dev_get_rtnl(dev)) { + __in_dev_get_rtnl(dev)->cnf.proxy_arp = 0; return 0; } return -ENXIO; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index ba2895a..74f2207 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -351,7 +351,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa) static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) { - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); @@ -449,7 +449,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg goto out; rc = -ENOBUFS; - if ((in_dev = __in_dev_get(dev)) == NULL) { + if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { in_dev = inetdev_init(dev); if (!in_dev) goto out; @@ -584,7 +584,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) if (colon) *colon = ':'; - if ((in_dev = __in_dev_get(dev)) != NULL) { + if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { if (tryaddrmatch) { /* Matthias Andree */ /* compare label and address (4.4BSD style) */ @@ -748,7 +748,7 @@ rarok: static int inet_gifconf(struct net_device *dev, char __user *buf, int len) { - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); struct in_ifaddr *ifa; struct ifreq ifr; int done = 0; @@ -791,7 +791,7 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope) struct in_device *in_dev; rcu_read_lock(); - in_dev = __in_dev_get(dev); + in_dev = __in_dev_get_rcu(dev); if (!in_dev) goto no_in_dev; @@ -818,7 +818,7 @@ no_in_dev: read_lock(&dev_base_lock); rcu_read_lock(); for (dev = dev_base; dev; dev = dev->next) { - if ((in_dev = __in_dev_get(dev)) == NULL) + if ((in_dev = __in_dev_get_rcu(dev)) == NULL) continue; for_primary_ifa(in_dev) { @@ -887,7 +887,7 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop if (dev) { rcu_read_lock(); - if ((in_dev = __in_dev_get(dev))) + if ((in_dev = __in_dev_get_rcu(dev))) addr = confirm_addr_indev(in_dev, dst, local, scope); rcu_read_unlock(); @@ -897,7 +897,7 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop read_lock(&dev_base_lock); rcu_read_lock(); for (dev = dev_base; dev; dev = dev->next) { - if ((in_dev = __in_dev_get(dev))) { + if ((in_dev = __in_dev_get_rcu(dev))) { addr = confirm_addr_indev(in_dev, dst, local, scope); if (addr) break; @@ -957,7 +957,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = ptr; - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); @@ -1078,7 +1078,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) if (idx > s_idx) s_ip_idx = 0; rcu_read_lock(); - if ((in_dev = __in_dev_get(dev)) == NULL) { + if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { rcu_read_unlock(); continue; } @@ -1149,7 +1149,7 @@ void inet_forward_change(void) for (dev = dev_base; dev; dev = dev->next) { struct in_device *in_dev; rcu_read_lock(); - in_dev = __in_dev_get(dev); + in_dev = __in_dev_get_rcu(dev); if (in_dev) in_dev->cnf.forwarding = on; rcu_read_unlock(); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 4e1379f..e61bc71 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -173,7 +173,7 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, no_addr = rpf = 0; rcu_read_lock(); - in_dev = __in_dev_get(dev); + in_dev = __in_dev_get_rcu(dev); if (in_dev) { no_addr = in_dev->ifa_list == NULL; rpf = IN_DEV_RPFILTER(in_dev); @@ -607,7 +607,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = ptr; - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); if (event == NETDEV_UNREGISTER) { fib_disable_ip(dev, 2); diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index d41219e..186f20c 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -1087,7 +1087,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, rta->rta_oif = &dev->ifindex; if (colon) { struct in_ifaddr *ifa; - struct in_device *in_dev = __in_dev_get(dev); + struct in_device *in_dev = __in_dev_get_rtnl(dev); if (!in_dev) return -ENODEV; *colon = ':'; @@ -1268,7 +1268,7 @@ int fib_sync_up(struct net_device *dev) } if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP)) continue; - if (nh->nh_dev != dev || __in_dev_get(dev) == NULL) + if (nh->nh_dev != dev || !__in_dev_get_rtnl(dev)) continue; alive++; spin_lock_bh(&fib_multipath_lock); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 70c44e4..8b6d393 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1323,7 +1323,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) } if (dev) { imr->imr_ifindex = dev->ifindex; - idev = __in_dev_get(dev); + idev = __in_dev_get_rtnl(dev); } return idev; } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index f0d5740..896ce3f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1104,10 +1104,10 @@ static int ipgre_open(struct net_device *dev) return -EADDRNOTAVAIL; dev = rt->u.dst.dev; ip_rt_put(rt); - if (__in_dev_get(dev) == NULL) + if (__in_dev_get_rtnl(dev) == NULL) return -EADDRNOTAVAIL; t->mlink = dev->ifindex; - ip_mc_inc_group(__in_dev_get(dev), t->parms.iph.daddr); + ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); } return 0; } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9dbf590..302b7eb 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -149,7 +149,7 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v) if (err == 0 && (dev = __dev_get_by_name(p.name)) != NULL) { dev->flags |= IFF_MULTICAST; - in_dev = __in_dev_get(dev); + in_dev = __in_dev_get_rtnl(dev); if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL) goto failure; in_dev->cnf.rp_filter = 0; @@ -278,7 +278,7 @@ static int vif_delete(int vifi) dev_set_allmulti(dev, -1); - if ((in_dev = __in_dev_get(dev)) != NULL) { + if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { in_dev->cnf.mc_forwarding--; ip_rt_multicast_event(in_dev); } @@ -421,7 +421,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock) return -EINVAL; } - if ((in_dev = __in_dev_get(dev)) == NULL) + if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) return -EADDRNOTAVAIL; in_dev->cnf.mc_forwarding++; dev_set_allmulti(dev, +1); diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c index 577bac2..186646e 100644 --- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c +++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c @@ -58,7 +58,7 @@ static int help(struct sk_buff **pskb, goto out; rcu_read_lock(); - in_dev = __in_dev_get(rt->u.dst.dev); + in_dev = __in_dev_get_rcu(rt->u.dst.dev); if (in_dev != NULL) { for_primary_ifa(in_dev) { if (ifa->ifa_broadcast == iph->daddr) { diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 715cb61..5245bfd 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -93,7 +93,7 @@ redirect_target(struct sk_buff **pskb, newdst = 0; rcu_read_lock(); - indev = __in_dev_get((*pskb)->dev); + indev = __in_dev_get_rcu((*pskb)->dev); if (indev && (ifa = indev->ifa_list)) newdst = ifa->ifa_local; rcu_read_unlock(); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8549f26..381dd6a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2128,7 +2128,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, struct in_device *in_dev; rcu_read_lock(); - if ((in_dev = __in_dev_get(dev)) != NULL) { + if ((in_dev = __in_dev_get_rcu(dev)) != NULL) { int our = ip_check_mc(in_dev, daddr, saddr, skb->nh.iph->protocol); if (our @@ -2443,7 +2443,9 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) err = -ENODEV; if (dev_out == NULL) goto out; - if (__in_dev_get(dev_out) == NULL) { + + /* RACE: Check return value of inet_select_addr instead. */ + if (__in_dev_get_rtnl(dev_out) == NULL) { dev_put(dev_out); goto out; /* Wrong error code */ } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4e509e5..a970b47 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1806,7 +1806,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) } for (dev = dev_base; dev != NULL; dev = dev->next) { - struct in_device * in_dev = __in_dev_get(dev); + struct in_device * in_dev = __in_dev_get_rtnl(dev); if (in_dev && (dev->flags & IFF_UP)) { struct in_ifaddr * ifa; diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 071cd2c..953e255 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -310,7 +310,7 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev) #ifdef CONFIG_INET IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n"); rcu_read_lock(); - in_dev = __in_dev_get(dev); + in_dev = __in_dev_get_rcu(dev); if (in_dev == NULL) goto out; if (in_dev->ifa_list) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index e7025be..f01d1c9 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -147,7 +147,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, struct sctp_sockaddr_entry *addr; rcu_read_lock(); - if ((in_dev = __in_dev_get(dev)) == NULL) { + if ((in_dev = __in_dev_get_rcu(dev)) == NULL) { rcu_read_unlock(); return; } -- cgit v0.10.2 From 3e56a40bb36f1f73b4eac2ffe267c5357811e321 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 3 Oct 2005 14:36:32 -0700 Subject: [IPV4]: Get rid of bogus __in_put_dev in pktgen This patch gets rid of a bogus __in_dev_put() in pktgen.c. This was spotted by Suzanne Wood. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 44de070..5f043d3 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1673,7 +1673,6 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) pkt_dev->saddr_min = in_dev->ifa_list->ifa_address; pkt_dev->saddr_max = pkt_dev->saddr_min; } - __in_dev_put(in_dev); } rcu_read_unlock(); } -- cgit v0.10.2 From 7ce312467edc270fcbd8a699efabb37ce1802b98 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Oct 2005 16:07:30 -0700 Subject: [IPV4]: Update icmp sysctl docs and disable broadcast ECHO/TIMESTAMP by default It's not a good idea to be smurf'able by default. The few people who need this can turn it on. Signed-off-by: David S. Miller diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index ab65714..b433c8a 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -355,10 +355,14 @@ ip_dynaddr - BOOLEAN Default: 0 icmp_echo_ignore_all - BOOLEAN + If set non-zero, then the kernel will ignore all ICMP ECHO + requests sent to it. + Default: 0 + icmp_echo_ignore_broadcasts - BOOLEAN - If either is set to true, then the kernel will ignore either all - ICMP ECHO requests sent to it or just those to broadcast/multicast - addresses, respectively. + If set non-zero, then the kernel will ignore all ICMP ECHO and + TIMESTAMP requests sent to it via broadcast/multicast. + Default: 1 icmp_ratelimit - INTEGER Limit the maximal rates for sending ICMP packets whose type matches diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 24eb56a..90dca71 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -188,7 +188,7 @@ struct icmp_err icmp_err_convert[] = { /* Control parameters for ECHO replies. */ int sysctl_icmp_echo_ignore_all; -int sysctl_icmp_echo_ignore_broadcasts; +int sysctl_icmp_echo_ignore_broadcasts = 1; /* Control parameter - ignore bogus broadcast responses? */ int sysctl_icmp_ignore_bogus_error_responses; -- cgit v0.10.2 From ed39f731ab2e77e58122232f6e27333331d7793d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Oct 2005 16:25:23 -0700 Subject: [TG3]: Update driver version and release date. Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index fee0e6e..1802c3b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.41" -#define DRV_MODULE_RELDATE "September 27, 2005" +#define DRV_MODULE_VERSION "3.42" +#define DRV_MODULE_RELDATE "Oct 3, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v0.10.2 From 3115624eda34d0f4e673fc6bcea36b7ad701ee33 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 3 Oct 2005 17:37:02 -0700 Subject: [SPARC]: "extern inline" doesn't make much sense. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index bc015e9..279a626 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -457,7 +457,7 @@ void __init time_init(void) sbus_time_init(); } -extern __inline__ unsigned long do_gettimeoffset(void) +static inline unsigned long do_gettimeoffset(void) { return (*master_l10_counter >> 10) & 0x1fffff; } diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c89a803..c664b96 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -260,7 +260,7 @@ static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); } /* to find an entry in a top-level page table... */ -extern inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address) +static inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address) { return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); } /* Find an entry in the second-level page table.. */ diff --git a/include/asm-sparc/btfixup.h b/include/asm-sparc/btfixup.h index b84c96c..6b29503 100644 --- a/include/asm-sparc/btfixup.h +++ b/include/asm-sparc/btfixup.h @@ -51,7 +51,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); #define BTFIXUPDEF_SIMM13(__name) \ extern unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ - extern __inline__ unsigned int ___sf_##__name(void) { \ + static inline unsigned int ___sf_##__name(void) { \ unsigned int ret; \ __asm__ ("or %%g0, ___s_" #__name ", %0" : "=r"(ret)); \ return ret; \ @@ -59,7 +59,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); #define BTFIXUPDEF_SIMM13_INIT(__name,__val) \ extern unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ - extern __inline__ unsigned int ___sf_##__name(void) { \ + static inline unsigned int ___sf_##__name(void) { \ unsigned int ret; \ __asm__ ("or %%g0, ___s_" #__name "__btset_" #__val ", %0" : "=r"(ret));\ return ret; \ @@ -73,7 +73,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 ___as_##__name[2]; \ - extern __inline__ unsigned int ___af_##__name(void) { \ + static inline unsigned int ___af_##__name(void) { \ unsigned int ret; \ __asm__ ("or %%g0, ___a_" #__name ", %0" : "=r"(ret)); \ return ret; \ @@ -81,7 +81,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); #define BTFIXUPDEF_HALF_INIT(__name,__val) \ extern unsigned int ___af_##__name(void) __attribute_const__; \ extern unsigned ___as_##__name[2]; \ - extern __inline__ unsigned int ___af_##__name(void) { \ + static inline unsigned int ___af_##__name(void) { \ unsigned int ret; \ __asm__ ("or %%g0, ___a_" #__name "__btset_" #__val ", %0" : "=r"(ret));\ return ret; \ @@ -92,7 +92,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); #define BTFIXUPDEF_SETHI(__name) \ extern unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ - extern __inline__ unsigned int ___hf_##__name(void) { \ + static inline unsigned int ___hf_##__name(void) { \ unsigned int ret; \ __asm__ ("sethi %%hi(___h_" #__name "), %0" : "=r"(ret)); \ return ret; \ @@ -100,7 +100,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); #define BTFIXUPDEF_SETHI_INIT(__name,__val) \ extern unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ - extern __inline__ unsigned int ___hf_##__name(void) { \ + static inline unsigned int ___hf_##__name(void) { \ unsigned int ret; \ __asm__ ("sethi %%hi(___h_" #__name "__btset_" #__val "), %0" : \ "=r"(ret)); \ diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h index e6316fd..a10522c 100644 --- a/include/asm-sparc/cache.h +++ b/include/asm-sparc/cache.h @@ -27,7 +27,7 @@ */ /* First, cache-tag access. */ -extern __inline__ unsigned int get_icache_tag(int setnum, int tagnum) +static inline unsigned int get_icache_tag(int setnum, int tagnum) { unsigned int vaddr, retval; @@ -38,7 +38,7 @@ extern __inline__ unsigned int get_icache_tag(int setnum, int tagnum) return retval; } -extern __inline__ void put_icache_tag(int setnum, int tagnum, unsigned int entry) +static inline void put_icache_tag(int setnum, int tagnum, unsigned int entry) { unsigned int vaddr; @@ -51,7 +51,7 @@ extern __inline__ void put_icache_tag(int setnum, int tagnum, unsigned int entry /* Second cache-data access. The data is returned two-32bit quantities * at a time. */ -extern __inline__ void get_icache_data(int setnum, int tagnum, int subblock, +static inline void get_icache_data(int setnum, int tagnum, int subblock, unsigned int *data) { unsigned int value1, value2, vaddr; @@ -67,7 +67,7 @@ extern __inline__ void get_icache_data(int setnum, int tagnum, int subblock, data[0] = value1; data[1] = value2; } -extern __inline__ void put_icache_data(int setnum, int tagnum, int subblock, +static inline void put_icache_data(int setnum, int tagnum, int subblock, unsigned int *data) { unsigned int value1, value2, vaddr; @@ -92,35 +92,35 @@ extern __inline__ void put_icache_data(int setnum, int tagnum, int subblock, */ /* Flushes which clear out both the on-chip and external caches */ -extern __inline__ void flush_ei_page(unsigned int addr) +static inline void flush_ei_page(unsigned int addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_PAGE) : "memory"); } -extern __inline__ void flush_ei_seg(unsigned int addr) +static inline void flush_ei_seg(unsigned int addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_SEG) : "memory"); } -extern __inline__ void flush_ei_region(unsigned int addr) +static inline void flush_ei_region(unsigned int addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_REGION) : "memory"); } -extern __inline__ void flush_ei_ctx(unsigned int addr) +static inline void flush_ei_ctx(unsigned int addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_CTX) : "memory"); } -extern __inline__ void flush_ei_user(unsigned int addr) +static inline void flush_ei_user(unsigned int addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_USER) : diff --git a/include/asm-sparc/cypress.h b/include/asm-sparc/cypress.h index fc92fc8..99599533 100644 --- a/include/asm-sparc/cypress.h +++ b/include/asm-sparc/cypress.h @@ -48,25 +48,25 @@ #define CYPRESS_NFAULT 0x00000002 #define CYPRESS_MENABLE 0x00000001 -extern __inline__ void cypress_flush_page(unsigned long page) +static inline void cypress_flush_page(unsigned long page) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (page), "i" (ASI_M_FLUSH_PAGE)); } -extern __inline__ void cypress_flush_segment(unsigned long addr) +static inline void cypress_flush_segment(unsigned long addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_SEG)); } -extern __inline__ void cypress_flush_region(unsigned long addr) +static inline void cypress_flush_region(unsigned long addr) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : : "r" (addr), "i" (ASI_M_FLUSH_REGION)); } -extern __inline__ void cypress_flush_context(void) +static inline void cypress_flush_context(void) { __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : : "i" (ASI_M_FLUSH_CTX)); diff --git a/include/asm-sparc/delay.h b/include/asm-sparc/delay.h index 6edf2cb..7ec8e9f 100644 --- a/include/asm-sparc/delay.h +++ b/include/asm-sparc/delay.h @@ -10,7 +10,7 @@ #include #include -extern __inline__ void __delay(unsigned long loops) +static inline void __delay(unsigned long loops) { __asm__ __volatile__("cmp %0, 0\n\t" "1: bne 1b\n\t" diff --git a/include/asm-sparc/dma.h b/include/asm-sparc/dma.h index 07e6368..8ec206a 100644 --- a/include/asm-sparc/dma.h +++ b/include/asm-sparc/dma.h @@ -198,7 +198,7 @@ extern void dvma_init(struct sbus_bus *); /* Pause until counter runs out or BIT isn't set in the DMA condition * register. */ -extern __inline__ void sparc_dma_pause(struct sparc_dma_registers *regs, +static inline void sparc_dma_pause(struct sparc_dma_registers *regs, unsigned long bit) { int ctr = 50000; /* Let's find some bugs ;) */ diff --git a/include/asm-sparc/iommu.h b/include/asm-sparc/iommu.h index 8171362..70c589c 100644 --- a/include/asm-sparc/iommu.h +++ b/include/asm-sparc/iommu.h @@ -108,12 +108,12 @@ struct iommu_struct { struct bit_map usemap; }; -extern __inline__ void iommu_invalidate(struct iommu_regs *regs) +static inline void iommu_invalidate(struct iommu_regs *regs) { regs->tlbflush = 0; } -extern __inline__ void iommu_invalidate_page(struct iommu_regs *regs, unsigned long ba) +static inline void iommu_invalidate_page(struct iommu_regs *regs, unsigned long ba) { regs->pageflush = (ba & PAGE_MASK); } diff --git a/include/asm-sparc/kdebug.h b/include/asm-sparc/kdebug.h index 3ea4916..fba9248 100644 --- a/include/asm-sparc/kdebug.h +++ b/include/asm-sparc/kdebug.h @@ -46,7 +46,7 @@ struct kernel_debug { extern struct kernel_debug *linux_dbvec; /* Use this macro in C-code to enter the debugger. */ -extern __inline__ void sp_enter_debugger(void) +static inline void sp_enter_debugger(void) { __asm__ __volatile__("jmpl %0, %%o7\n\t" "nop\n\t" : : diff --git a/include/asm-sparc/mbus.h b/include/asm-sparc/mbus.h index 5f27490..ecacdf4 100644 --- a/include/asm-sparc/mbus.h +++ b/include/asm-sparc/mbus.h @@ -83,7 +83,7 @@ extern unsigned int hwbug_bitmask; */ #define TBR_ID_SHIFT 20 -extern __inline__ int get_cpuid(void) +static inline int get_cpuid(void) { register int retval; __asm__ __volatile__("rd %%tbr, %0\n\t" @@ -93,7 +93,7 @@ extern __inline__ int get_cpuid(void) return (retval & 3); } -extern __inline__ int get_modid(void) +static inline int get_modid(void) { return (get_cpuid() | 0x8); } diff --git a/include/asm-sparc/msi.h b/include/asm-sparc/msi.h index b69543d..ff72cbd 100644 --- a/include/asm-sparc/msi.h +++ b/include/asm-sparc/msi.h @@ -19,7 +19,7 @@ #define MSI_ASYNC_MODE 0x80000000 /* Operate the MSI asynchronously */ -extern __inline__ void msi_set_sync(void) +static inline void msi_set_sync(void) { __asm__ __volatile__ ("lda [%0] %1, %%g3\n\t" "andn %%g3, %2, %%g3\n\t" diff --git a/include/asm-sparc/mxcc.h b/include/asm-sparc/mxcc.h index 60ef9d6..128fe97 100644 --- a/include/asm-sparc/mxcc.h +++ b/include/asm-sparc/mxcc.h @@ -85,7 +85,7 @@ #ifndef __ASSEMBLY__ -extern __inline__ void mxcc_set_stream_src(unsigned long *paddr) +static inline void mxcc_set_stream_src(unsigned long *paddr) { unsigned long data0 = paddr[0]; unsigned long data1 = paddr[1]; @@ -98,7 +98,7 @@ extern __inline__ void mxcc_set_stream_src(unsigned long *paddr) "i" (ASI_M_MXCC) : "g2", "g3"); } -extern __inline__ void mxcc_set_stream_dst(unsigned long *paddr) +static inline void mxcc_set_stream_dst(unsigned long *paddr) { unsigned long data0 = paddr[0]; unsigned long data1 = paddr[1]; @@ -111,7 +111,7 @@ extern __inline__ void mxcc_set_stream_dst(unsigned long *paddr) "i" (ASI_M_MXCC) : "g2", "g3"); } -extern __inline__ unsigned long mxcc_get_creg(void) +static inline unsigned long mxcc_get_creg(void) { unsigned long mxcc_control; @@ -125,7 +125,7 @@ extern __inline__ unsigned long mxcc_get_creg(void) return mxcc_control; } -extern __inline__ void mxcc_set_creg(unsigned long mxcc_control) +static inline void mxcc_set_creg(unsigned long mxcc_control) { __asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r" (mxcc_control), "r" (MXCC_CREG), diff --git a/include/asm-sparc/obio.h b/include/asm-sparc/obio.h index 62e1d77..47854a2 100644 --- a/include/asm-sparc/obio.h +++ b/include/asm-sparc/obio.h @@ -98,7 +98,7 @@ #ifndef __ASSEMBLY__ -extern __inline__ int bw_get_intr_mask(int sbus_level) +static inline int bw_get_intr_mask(int sbus_level) { int mask; @@ -109,7 +109,7 @@ extern __inline__ int bw_get_intr_mask(int sbus_level) return mask; } -extern __inline__ void bw_clear_intr_mask(int sbus_level, int mask) +static inline void bw_clear_intr_mask(int sbus_level, int mask) { __asm__ __volatile__ ("stha %0, [%1] %2" : : "r" (mask), @@ -117,7 +117,7 @@ extern __inline__ void bw_clear_intr_mask(int sbus_level, int mask) "i" (ASI_M_CTL)); } -extern __inline__ unsigned bw_get_prof_limit(int cpu) +static inline unsigned bw_get_prof_limit(int cpu) { unsigned limit; @@ -128,7 +128,7 @@ extern __inline__ unsigned bw_get_prof_limit(int cpu) return limit; } -extern __inline__ void bw_set_prof_limit(int cpu, unsigned limit) +static inline void bw_set_prof_limit(int cpu, unsigned limit) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (limit), @@ -136,7 +136,7 @@ extern __inline__ void bw_set_prof_limit(int cpu, unsigned limit) "i" (ASI_M_CTL)); } -extern __inline__ unsigned bw_get_ctrl(int cpu) +static inline unsigned bw_get_ctrl(int cpu) { unsigned ctrl; @@ -147,7 +147,7 @@ extern __inline__ unsigned bw_get_ctrl(int cpu) return ctrl; } -extern __inline__ void bw_set_ctrl(int cpu, unsigned ctrl) +static inline void bw_set_ctrl(int cpu, unsigned ctrl) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (ctrl), @@ -157,7 +157,7 @@ extern __inline__ void bw_set_ctrl(int cpu, unsigned ctrl) extern unsigned char cpu_leds[32]; -extern __inline__ void show_leds(int cpuid) +static inline void show_leds(int cpuid) { cpuid &= 0x1e; __asm__ __volatile__ ("stba %0, [%1] %2" : : @@ -166,7 +166,7 @@ extern __inline__ void show_leds(int cpuid) "i" (ASI_M_CTL)); } -extern __inline__ unsigned cc_get_ipen(void) +static inline unsigned cc_get_ipen(void) { unsigned pending; @@ -177,7 +177,7 @@ extern __inline__ unsigned cc_get_ipen(void) return pending; } -extern __inline__ void cc_set_iclr(unsigned clear) +static inline void cc_set_iclr(unsigned clear) { __asm__ __volatile__ ("stha %0, [%1] %2" : : "r" (clear), @@ -185,7 +185,7 @@ extern __inline__ void cc_set_iclr(unsigned clear) "i" (ASI_M_MXCC)); } -extern __inline__ unsigned cc_get_imsk(void) +static inline unsigned cc_get_imsk(void) { unsigned mask; @@ -196,7 +196,7 @@ extern __inline__ unsigned cc_get_imsk(void) return mask; } -extern __inline__ void cc_set_imsk(unsigned mask) +static inline void cc_set_imsk(unsigned mask) { __asm__ __volatile__ ("stha %0, [%1] %2" : : "r" (mask), @@ -204,7 +204,7 @@ extern __inline__ void cc_set_imsk(unsigned mask) "i" (ASI_M_MXCC)); } -extern __inline__ unsigned cc_get_imsk_other(int cpuid) +static inline unsigned cc_get_imsk_other(int cpuid) { unsigned mask; @@ -215,7 +215,7 @@ extern __inline__ unsigned cc_get_imsk_other(int cpuid) return mask; } -extern __inline__ void cc_set_imsk_other(int cpuid, unsigned mask) +static inline void cc_set_imsk_other(int cpuid, unsigned mask) { __asm__ __volatile__ ("stha %0, [%1] %2" : : "r" (mask), @@ -223,7 +223,7 @@ extern __inline__ void cc_set_imsk_other(int cpuid, unsigned mask) "i" (ASI_M_CTL)); } -extern __inline__ void cc_set_igen(unsigned gen) +static inline void cc_set_igen(unsigned gen) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (gen), @@ -239,7 +239,7 @@ extern __inline__ void cc_set_igen(unsigned gen) #define IGEN_MESSAGE(bcast, devid, sid, levels) \ (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels)) -extern __inline__ void sun4d_send_ipi(int cpu, int level) +static inline void sun4d_send_ipi(int cpu, int level) { cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1))); } diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h index 97052ba..3864474 100644 --- a/include/asm-sparc/pci.h +++ b/include/asm-sparc/pci.h @@ -15,12 +15,12 @@ #define PCI_IRQ_NONE 0xffffffff -extern inline void pcibios_set_master(struct pci_dev *dev) +static inline void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ } -extern inline void pcibios_penalize_isa_irq(int irq, int active) +static inline void pcibios_penalize_isa_irq(int irq, int active) { /* We don't do dynamic PCI IRQ allocation */ } @@ -137,7 +137,7 @@ extern void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) +static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) { return 1; } diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index 8395ad2..ae883f2 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -154,7 +154,7 @@ BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t) BTFIXUPDEF_CALL(void, pte_clear, pte_t *) BTFIXUPDEF_CALL(int, pte_read, pte_t) -extern __inline__ int pte_none(pte_t pte) +static inline int pte_none(pte_t pte) { return !(pte_val(pte) & ~BTFIXUP_SETHI(none_mask)); } @@ -167,7 +167,7 @@ BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t) BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t) BTFIXUPDEF_CALL(void, pmd_clear, pmd_t *) -extern __inline__ int pmd_none(pmd_t pmd) +static inline int pmd_none(pmd_t pmd) { return !(pmd_val(pmd) & ~BTFIXUP_SETHI(none_mask)); } @@ -195,19 +195,19 @@ BTFIXUPDEF_HALF(pte_dirtyi) BTFIXUPDEF_HALF(pte_youngi) extern int pte_write(pte_t pte) __attribute_const__; -extern __inline__ int pte_write(pte_t pte) +static 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 __inline__ int pte_dirty(pte_t pte) +static 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 __inline__ int pte_young(pte_t pte) +static inline int pte_young(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_youngi); } @@ -218,7 +218,7 @@ extern __inline__ int pte_young(pte_t pte) BTFIXUPDEF_HALF(pte_filei) extern int pte_file(pte_t pte) __attribute_const__; -extern __inline__ int pte_file(pte_t pte) +static inline int pte_file(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_filei); } @@ -230,19 +230,19 @@ BTFIXUPDEF_HALF(pte_mkcleani) BTFIXUPDEF_HALF(pte_mkoldi) extern pte_t pte_wrprotect(pte_t pte) __attribute_const__; -extern __inline__ pte_t pte_wrprotect(pte_t pte) +static 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 __inline__ pte_t pte_mkclean(pte_t pte) +static 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 __inline__ pte_t pte_mkold(pte_t pte) +static inline pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi)); } @@ -279,7 +279,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 __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) | pgprot_val(newprot)); @@ -386,13 +386,13 @@ extern struct ctx_list ctx_used; /* Head of used contexts list */ #define NO_CONTEXT -1 -extern __inline__ void remove_from_ctx_list(struct ctx_list *entry) +static inline void remove_from_ctx_list(struct ctx_list *entry) { entry->next->prev = entry->prev; entry->prev->next = entry->next; } -extern __inline__ void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry) +static inline void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry) { entry->next = head; (entry->prev = head->prev)->next = entry; @@ -401,7 +401,7 @@ extern __inline__ void add_to_ctx_list(struct ctx_list *head, struct ctx_list *e #define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry) #define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry) -extern __inline__ unsigned long +static inline unsigned long __get_phys (unsigned long addr) { switch (sparc_cpu_model){ @@ -416,7 +416,7 @@ __get_phys (unsigned long addr) } } -extern __inline__ int +static inline int __get_iospace (unsigned long addr) { switch (sparc_cpu_model){ diff --git a/include/asm-sparc/pgtsrmmu.h b/include/asm-sparc/pgtsrmmu.h index ee3b9d9..edeb981 100644 --- a/include/asm-sparc/pgtsrmmu.h +++ b/include/asm-sparc/pgtsrmmu.h @@ -148,7 +148,7 @@ extern void *srmmu_nocache_pool; #define __nocache_fix(VADDR) __va(__nocache_pa(VADDR)) /* Accessing the MMU control register. */ -extern __inline__ unsigned int srmmu_get_mmureg(void) +static inline unsigned int srmmu_get_mmureg(void) { unsigned int retval; __asm__ __volatile__("lda [%%g0] %1, %0\n\t" : @@ -157,14 +157,14 @@ extern __inline__ unsigned int srmmu_get_mmureg(void) return retval; } -extern __inline__ void srmmu_set_mmureg(unsigned long regval) +static inline void srmmu_set_mmureg(unsigned long regval) { __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : : "r" (regval), "i" (ASI_M_MMUREGS) : "memory"); } -extern __inline__ void srmmu_set_ctable_ptr(unsigned long paddr) +static inline void srmmu_set_ctable_ptr(unsigned long paddr) { paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); __asm__ __volatile__("sta %0, [%1] %2\n\t" : : @@ -173,7 +173,7 @@ extern __inline__ void srmmu_set_ctable_ptr(unsigned long paddr) "memory"); } -extern __inline__ unsigned long srmmu_get_ctable_ptr(void) +static inline unsigned long srmmu_get_ctable_ptr(void) { unsigned int retval; @@ -184,14 +184,14 @@ extern __inline__ unsigned long srmmu_get_ctable_ptr(void) return (retval & SRMMU_CTX_PMASK) << 4; } -extern __inline__ void srmmu_set_context(int context) +static inline void srmmu_set_context(int context) { __asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r" (context), "r" (SRMMU_CTX_REG), "i" (ASI_M_MMUREGS) : "memory"); } -extern __inline__ int srmmu_get_context(void) +static inline int srmmu_get_context(void) { register int retval; __asm__ __volatile__("lda [%1] %2, %0\n\t" : @@ -201,7 +201,7 @@ extern __inline__ int srmmu_get_context(void) return retval; } -extern __inline__ unsigned int srmmu_get_fstatus(void) +static inline unsigned int srmmu_get_fstatus(void) { unsigned int retval; @@ -211,7 +211,7 @@ extern __inline__ unsigned int srmmu_get_fstatus(void) return retval; } -extern __inline__ unsigned int srmmu_get_faddr(void) +static inline unsigned int srmmu_get_faddr(void) { unsigned int retval; @@ -222,7 +222,7 @@ extern __inline__ unsigned int srmmu_get_faddr(void) } /* This is guaranteed on all SRMMU's. */ -extern __inline__ void srmmu_flush_whole_tlb(void) +static inline void srmmu_flush_whole_tlb(void) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : "r" (0x400), /* Flush entire TLB!! */ @@ -231,7 +231,7 @@ extern __inline__ void srmmu_flush_whole_tlb(void) } /* These flush types are not available on all chips... */ -extern __inline__ void srmmu_flush_tlb_ctx(void) +static inline void srmmu_flush_tlb_ctx(void) { __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : "r" (0x300), /* Flush TLB ctx.. */ @@ -239,7 +239,7 @@ extern __inline__ void srmmu_flush_tlb_ctx(void) } -extern __inline__ void srmmu_flush_tlb_region(unsigned long addr) +static inline void srmmu_flush_tlb_region(unsigned long addr) { addr &= SRMMU_PGDIR_MASK; __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : @@ -249,7 +249,7 @@ extern __inline__ void srmmu_flush_tlb_region(unsigned long addr) } -extern __inline__ void srmmu_flush_tlb_segment(unsigned long addr) +static inline void srmmu_flush_tlb_segment(unsigned long addr) { addr &= SRMMU_REAL_PMD_MASK; __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : @@ -258,7 +258,7 @@ extern __inline__ void srmmu_flush_tlb_segment(unsigned long addr) } -extern __inline__ void srmmu_flush_tlb_page(unsigned long page) +static inline void srmmu_flush_tlb_page(unsigned long page) { page &= PAGE_MASK; __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : @@ -267,7 +267,7 @@ extern __inline__ void srmmu_flush_tlb_page(unsigned long page) } -extern __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr) +static inline unsigned long srmmu_hwprobe(unsigned long vaddr) { unsigned long retval; @@ -279,7 +279,7 @@ extern __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr) return retval; } -extern __inline__ int +static inline int srmmu_get_pte (unsigned long addr) { register unsigned long entry; diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index 5a7a1a8..6fbb3f0 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -79,7 +79,7 @@ struct thread_struct { extern unsigned long thread_saved_pc(struct task_struct *t); /* Do necessary setup to start up a newly executed thread. */ -extern __inline__ void start_thread(struct pt_regs * regs, unsigned long pc, +static inline void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { register unsigned long zero asm("g1"); diff --git a/include/asm-sparc/psr.h b/include/asm-sparc/psr.h index 9778b8c..19c9780 100644 --- a/include/asm-sparc/psr.h +++ b/include/asm-sparc/psr.h @@ -38,7 +38,7 @@ #ifndef __ASSEMBLY__ /* Get the %psr register. */ -extern __inline__ unsigned int get_psr(void) +static inline unsigned int get_psr(void) { unsigned int psr; __asm__ __volatile__( @@ -53,7 +53,7 @@ extern __inline__ unsigned int get_psr(void) return psr; } -extern __inline__ void put_psr(unsigned int new_psr) +static inline void put_psr(unsigned int new_psr) { __asm__ __volatile__( "wr %0, 0x0, %%psr\n\t" @@ -72,7 +72,7 @@ extern __inline__ void put_psr(unsigned int new_psr) extern unsigned int fsr_storage; -extern __inline__ unsigned int get_fsr(void) +static inline unsigned int get_fsr(void) { unsigned int fsr = 0; diff --git a/include/asm-sparc/sbi.h b/include/asm-sparc/sbi.h index 739ccac..86a603a 100644 --- a/include/asm-sparc/sbi.h +++ b/include/asm-sparc/sbi.h @@ -65,7 +65,7 @@ struct sbi_regs { #ifndef __ASSEMBLY__ -extern __inline__ int acquire_sbi(int devid, int mask) +static inline int acquire_sbi(int devid, int mask) { __asm__ __volatile__ ("swapa [%2] %3, %0" : "=r" (mask) : @@ -75,7 +75,7 @@ extern __inline__ int acquire_sbi(int devid, int mask) return mask; } -extern __inline__ void release_sbi(int devid, int mask) +static inline void release_sbi(int devid, int mask) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (mask), @@ -83,7 +83,7 @@ extern __inline__ void release_sbi(int devid, int mask) "i" (ASI_M_CTL)); } -extern __inline__ void set_sbi_tid(int devid, int targetid) +static inline void set_sbi_tid(int devid, int targetid) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (targetid), @@ -91,7 +91,7 @@ extern __inline__ void set_sbi_tid(int devid, int targetid) "i" (ASI_M_CTL)); } -extern __inline__ int get_sbi_ctl(int devid, int cfgno) +static inline int get_sbi_ctl(int devid, int cfgno) { int cfg; @@ -102,7 +102,7 @@ extern __inline__ int get_sbi_ctl(int devid, int cfgno) return cfg; } -extern __inline__ void set_sbi_ctl(int devid, int cfgno, int cfg) +static inline void set_sbi_ctl(int devid, int cfgno, int cfg) { __asm__ __volatile__ ("sta %0, [%1] %2" : : "r" (cfg), diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h index 3a8b390..a13cddc 100644 --- a/include/asm-sparc/sbus.h +++ b/include/asm-sparc/sbus.h @@ -28,12 +28,12 @@ * numbers + offsets, and vice versa. */ -extern __inline__ unsigned long sbus_devaddr(int slotnum, unsigned long offset) +static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset) { return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset)); } -extern __inline__ int sbus_dev_slot(unsigned long dev_addr) +static inline int sbus_dev_slot(unsigned long dev_addr) { return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25); } @@ -80,7 +80,7 @@ struct sbus_bus { extern struct sbus_bus *sbus_root; -extern __inline__ int +static inline int sbus_is_slave(struct sbus_dev *dev) { /* XXX Have to write this for sun4c's */ diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h index 4f96d83..580c51d 100644 --- a/include/asm-sparc/smp.h +++ b/include/asm-sparc/smp.h @@ -60,22 +60,22 @@ BTFIXUPDEF_BLACKBOX(load_current) #define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5) #define smp_message_pass(target,msg,data,wait) BTFIXUP_CALL(smp_message_pass)(target,msg,data,wait) -extern __inline__ void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); } -extern __inline__ void xc1(smpfunc_t func, unsigned long arg1) +static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); } +static inline void xc1(smpfunc_t func, unsigned long arg1) { smp_cross_call(func, arg1, 0, 0, 0, 0); } -extern __inline__ void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) +static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2) { smp_cross_call(func, arg1, arg2, 0, 0, 0); } -extern __inline__ void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, +static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2, unsigned long arg3) { smp_cross_call(func, arg1, arg2, arg3, 0, 0); } -extern __inline__ void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, +static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) { smp_cross_call(func, arg1, arg2, arg3, arg4, 0); } -extern __inline__ void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2, +static inline void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); } -extern __inline__ int smp_call_function(void (*func)(void *info), void *info, int nonatomic, int wait) +static inline int smp_call_function(void (*func)(void *info), void *info, int nonatomic, int wait) { xc1((smpfunc_t)func, (unsigned long)info); return 0; @@ -84,16 +84,16 @@ extern __inline__ int smp_call_function(void (*func)(void *info), void *info, in extern __volatile__ int __cpu_number_map[NR_CPUS]; extern __volatile__ int __cpu_logical_map[NR_CPUS]; -extern __inline__ int cpu_logical_map(int cpu) +static inline int cpu_logical_map(int cpu) { return __cpu_logical_map[cpu]; } -extern __inline__ int cpu_number_map(int cpu) +static inline int cpu_number_map(int cpu) { return __cpu_number_map[cpu]; } -extern __inline__ int hard_smp4m_processor_id(void) +static inline int hard_smp4m_processor_id(void) { int cpuid; @@ -104,7 +104,7 @@ extern __inline__ int hard_smp4m_processor_id(void) return cpuid; } -extern __inline__ int hard_smp4d_processor_id(void) +static inline int hard_smp4d_processor_id(void) { int cpuid; @@ -114,7 +114,7 @@ extern __inline__ int hard_smp4d_processor_id(void) } #ifndef MODULE -extern __inline__ int hard_smp_processor_id(void) +static inline int hard_smp_processor_id(void) { int cpuid; @@ -136,7 +136,7 @@ extern __inline__ int hard_smp_processor_id(void) return cpuid; } #else -extern __inline__ int hard_smp_processor_id(void) +static inline int hard_smp_processor_id(void) { int cpuid; diff --git a/include/asm-sparc/smpprim.h b/include/asm-sparc/smpprim.h index 9b9c28e..e7b6d34 100644 --- a/include/asm-sparc/smpprim.h +++ b/include/asm-sparc/smpprim.h @@ -15,7 +15,7 @@ * atomic. */ -extern __inline__ __volatile__ char test_and_set(void *addr) +static inline __volatile__ char test_and_set(void *addr) { char state = 0; @@ -27,7 +27,7 @@ extern __inline__ __volatile__ char test_and_set(void *addr) } /* Initialize a spin-lock. */ -extern __inline__ __volatile__ smp_initlock(void *spinlock) +static inline __volatile__ smp_initlock(void *spinlock) { /* Unset the lock. */ *((unsigned char *) spinlock) = 0; @@ -36,7 +36,7 @@ extern __inline__ __volatile__ smp_initlock(void *spinlock) } /* This routine spins until it acquires the lock at ADDR. */ -extern __inline__ __volatile__ smp_lock(void *addr) +static inline __volatile__ smp_lock(void *addr) { while(test_and_set(addr) == 0xff) ; @@ -46,7 +46,7 @@ extern __inline__ __volatile__ smp_lock(void *addr) } /* This routine releases the lock at ADDR. */ -extern __inline__ __volatile__ smp_unlock(void *addr) +static inline __volatile__ smp_unlock(void *addr) { *((unsigned char *) addr) = 0; } diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h index 111727a..e344c98 100644 --- a/include/asm-sparc/spinlock.h +++ b/include/asm-sparc/spinlock.h @@ -17,7 +17,7 @@ #define __raw_spin_unlock_wait(lock) \ do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0) -extern __inline__ void __raw_spin_lock(raw_spinlock_t *lock) +static inline void __raw_spin_lock(raw_spinlock_t *lock) { __asm__ __volatile__( "\n1:\n\t" @@ -37,7 +37,7 @@ extern __inline__ void __raw_spin_lock(raw_spinlock_t *lock) : "g2", "memory", "cc"); } -extern __inline__ int __raw_spin_trylock(raw_spinlock_t *lock) +static inline int __raw_spin_trylock(raw_spinlock_t *lock) { unsigned int result; __asm__ __volatile__("ldstub [%1], %0" @@ -47,7 +47,7 @@ extern __inline__ int __raw_spin_trylock(raw_spinlock_t *lock) return (result == 0); } -extern __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) +static inline void __raw_spin_unlock(raw_spinlock_t *lock) { __asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory"); } @@ -78,7 +78,7 @@ extern __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) * * Unfortunately this scheme limits us to ~16,000,000 cpus. */ -extern __inline__ void __read_lock(raw_rwlock_t *rw) +static inline void __read_lock(raw_rwlock_t *rw) { register raw_rwlock_t *lp asm("g1"); lp = rw; @@ -98,7 +98,7 @@ do { unsigned long flags; \ local_irq_restore(flags); \ } while(0) -extern __inline__ void __read_unlock(raw_rwlock_t *rw) +static inline void __read_unlock(raw_rwlock_t *rw) { register raw_rwlock_t *lp asm("g1"); lp = rw; diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 3557781..1f6b71f 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -204,7 +204,7 @@ static inline unsigned long getipl(void) BTFIXUPDEF_CALL(void, ___xchg32, void) #endif -extern __inline__ unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) +static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) { #ifdef CONFIG_SMP __asm__ __volatile__("swap [%2], %0" diff --git a/include/asm-sparc/traps.h b/include/asm-sparc/traps.h index 6690ab9..f62c7f8 100644 --- a/include/asm-sparc/traps.h +++ b/include/asm-sparc/traps.h @@ -22,7 +22,7 @@ struct tt_entry { /* We set this to _start in system setup. */ extern struct tt_entry *sparc_ttable; -extern __inline__ unsigned long get_tbr(void) +static inline unsigned long get_tbr(void) { unsigned long tbr; -- cgit v0.10.2 From fdc657c66678551c7987dc23a78ae1a26251276f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Oct 2005 17:37:27 -0700 Subject: [SUNSU]: Fix bogus locking in sunsu_change_mouse_baud() The lock is not held when calling this function, so we shouldn't drop then reacquire it. Based upon a report from Jim MacBaine. Signed-off-by: David S. Miller diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 5959e67..656c0e8 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -518,11 +518,7 @@ static void sunsu_change_mouse_baud(struct uart_sunsu_port *up) quot = up->port.uartclk / (16 * new_baud); - spin_unlock(&up->port.lock); - sunsu_change_speed(&up->port, up->cflag, 0, quot); - - spin_lock(&up->port.lock); } static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *regs, int is_break) -- cgit v0.10.2 From c2681dd8c71c8fb4ca530f94536550fcd843aae4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 3 Oct 2005 12:03:13 -0700 Subject: [PATCH] skge: set mac address oops with bonding Skge driver was bringing link up/down when changing mac address. This doesn't work in the bonding environment, and is more effort than needed. Fixes-bug: http://bugzilla.kernel.org/show_bug.cgi?id=5271 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik diff --git a/drivers/net/skge.c b/drivers/net/skge.c index fd398da..c2e6484 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2837,21 +2837,29 @@ static void skge_netpoll(struct net_device *dev) static int skge_set_mac_address(struct net_device *dev, void *p) { struct skge_port *skge = netdev_priv(dev); - struct sockaddr *addr = p; - int err = 0; + struct skge_hw *hw = skge->hw; + unsigned port = skge->port; + const struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - skge_down(dev); + spin_lock_bh(&hw->phy_lock); memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8, + memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8, + memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - if (dev->flags & IFF_UP) - err = skge_up(dev); - return err; + + if (hw->chip_id == CHIP_ID_GENESIS) + xm_outaddr(hw, port, XM_SA, dev->dev_addr); + else { + gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); + gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); + } + spin_unlock_bh(&hw->phy_lock); + + return 0; } static const struct { -- cgit v0.10.2 From 0a1c80f1115b9a1aacf00a312a532ceef49dfa1b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 2 Oct 2005 22:42:11 -0700 Subject: [PATCH] ns83820: fix gfp flags type Fix implicit nocast warnings in ns83820 code: drivers/net/ns83820.c:603:46: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index e64df4d..1d123d2 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -584,7 +584,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) return 0; } -static inline int rx_refill(struct net_device *ndev, int gfp) +static inline int rx_refill(struct net_device *ndev, unsigned int gfp) { struct ns83820 *dev = PRIV(ndev); unsigned i; -- cgit v0.10.2 From 8cb6108baee9dcd1dc96f476fe217d6a6b53c994 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 2 Oct 2005 22:41:09 -0700 Subject: [PATCH] ieee80211: fix gfp flags type Fix implicit nocast warnings in ieee80211 code: net/ieee80211/ieee80211_tx.c:215:9: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index c9aaff3..f915367 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -207,7 +207,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) } static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - int gfp_mask) + unsigned int gfp_mask) { struct ieee80211_txb *txb; int i; -- cgit v0.10.2 From bb53d6d0e70cd0749a7844efc62cefeb24b134b6 Mon Sep 17 00:00:00 2001 From: Komuro Date: Mon, 3 Oct 2005 22:03:28 -0400 Subject: [netdrvr] fix smc91c92_cs multicast bug The smc91c92_cs multicast does not work if the count of multicast address is 1. Signed-off-by: Signed-off-by: Jeff Garzik diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index d652e1ed..c7cca84 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1832,7 +1832,7 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, { struct dev_mc_list *mc_addr; - for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) { + for (mc_addr = addrs; mc_addr && count-- > 0; mc_addr = mc_addr->next) { u_int position = ether_crc(6, mc_addr->dmi_addr); #ifndef final_version /* Verify multicast address. */ if ((mc_addr->dmi_addr[0] & 1) == 0) -- cgit v0.10.2 From 9123e0d78990246304fe681167b8d8097f1e02d7 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 30 Sep 2005 10:17:24 +0200 Subject: [PATCH] s390: qeth driver fixes From: Peter Tiedemann From: Frank Pavlic minor qeth fixes: - free old skb in qeth_realloc_headroom after duplicating skb - disable IPV6 support for Hipersockets devices - call ccw_device_set_offline on every channel regardless of the return value of the prior ccw_device_set_offline calls - allocate qdio structures in DMA-area - schedule recovery of appropriate card when cable has been inserted again. - add missing initialization of card->lock - write sequence number in skb->cb for SNA protocol which requires strictly serialized packets. Signed-off-by: Frank Pavlic diffstat: qeth.h | 2 ++ qeth_main.c | 37 +++++++++++++++++-------------------- 2 files changed, 19 insertions(+), 20 deletions(-) Signed-off-by: Jeff Garzik diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 2ad4797..9963479 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h @@ -686,6 +686,7 @@ struct qeth_seqno { __u32 pdu_hdr; __u32 pdu_hdr_ack; __u16 ipa; + __u32 pkt_seqno; }; struct qeth_reply { @@ -848,6 +849,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size) "on interface %s", QETH_CARD_IFNAME(card)); return -ENOMEM; } + kfree_skb(*skb); *skb = new_skb; } return 0; diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 71de834..bd28e24 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -511,7 +511,7 @@ static int __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) { struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; - int rc = 0; + int rc = 0, rc2 = 0, rc3 = 0; enum qeth_card_states recover_flag; QETH_DBF_TEXT(setup, 3, "setoffl"); @@ -523,11 +523,13 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) CARD_BUS_ID(card)); return -ERESTARTSYS; } - if ((rc = ccw_device_set_offline(CARD_DDEV(card))) || - (rc = ccw_device_set_offline(CARD_WDEV(card))) || - (rc = ccw_device_set_offline(CARD_RDEV(card)))) { + rc = ccw_device_set_offline(CARD_DDEV(card)); + rc2 = ccw_device_set_offline(CARD_WDEV(card)); + rc3 = ccw_device_set_offline(CARD_RDEV(card)); + if (!rc) + rc = (rc2) ? rc2 : rc3; + if (rc) QETH_DBF_TEXT_(setup, 2, "1err%d", rc); - } if (recover_flag == CARD_STATE_UP) card->state = CARD_STATE_RECOVER; qeth_notify_processes(); @@ -1046,6 +1048,7 @@ qeth_setup_card(struct qeth_card *card) spin_lock_init(&card->vlanlock); card->vlangrp = NULL; #endif + spin_lock_init(&card->lock); spin_lock_init(&card->ip_lock); spin_lock_init(&card->thread_mask_lock); card->thread_start_mask = 0; @@ -1626,16 +1629,6 @@ qeth_cmd_timeout(unsigned long data) spin_unlock_irqrestore(&reply->card->lock, flags); } -static void -qeth_reset_ip_addresses(struct qeth_card *card) -{ - QETH_DBF_TEXT(trace, 2, "rstipadd"); - - qeth_clear_ip_list(card, 0, 1); - /* this function will also schedule the SET_IP_THREAD */ - qeth_set_multicast_list(card->dev); -} - static struct qeth_ipa_cmd * qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) { @@ -1664,9 +1657,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) "IP address reset.\n", QETH_CARD_IFNAME(card), card->info.chpid); - card->lan_online = 1; netif_carrier_on(card->dev); - qeth_reset_ip_addresses(card); + qeth_schedule_recovery(card); return NULL; case IPA_CMD_REGISTER_LOCAL_ADDR: QETH_DBF_TEXT(trace,3, "irla"); @@ -2387,6 +2379,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, skb_pull(skb, VLAN_HLEN); } #endif + *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; return vlan_id; } @@ -3014,7 +3007,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card) return -ENOMEM; } for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){ - ptr = (void *) __get_free_page(GFP_KERNEL); + ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA); if (!ptr) { while (j > 0) free_page((unsigned long) @@ -3058,7 +3051,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) if (card->qdio.state == QETH_QDIO_ALLOCATED) return 0; - card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL); + card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), + GFP_KERNEL|GFP_DMA); if (!card->qdio.in_q) return - ENOMEM; QETH_DBF_TEXT(setup, 2, "inq"); @@ -3083,7 +3077,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) } for (i = 0; i < card->qdio.no_out_queues; ++i){ card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), - GFP_KERNEL); + GFP_KERNEL|GFP_DMA); if (!card->qdio.out_qs[i]){ while (i > 0) kfree(card->qdio.out_qs[--i]); @@ -6470,6 +6464,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply, if (cmd->hdr.prot_version == QETH_PROT_IPV4) { card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; + /* Disable IPV6 support hard coded for Hipersockets */ + if(card->info.type == QETH_CARD_TYPE_IQD) + card->options.ipa4.supported_funcs &= ~IPA_IPV6; } else { #ifdef CONFIG_QETH_IPV6 card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; -- cgit v0.10.2 From 217df670d9a4da036d68b22500ac06128811d5c8 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Mon, 26 Sep 2005 16:11:50 -0700 Subject: [PATCH] fix bonding crash, remove old ABI support David S. Miller wrote: >I think removing support for older ifenslave binaries is >the least painful solution to this problem. This patch removes backwards compatibility for old ifenslave binaries (ifenslave prior to verison 1.0.0). I did not similarly modify ifenslave itself; with sysfs on the horizon, I don't see that as being worthwhile. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bf81cd45..fd62e43 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -487,6 +487,8 @@ * * Added xmit_hash_policy_layer34() * - Modified by Jay Vosburgh to also support mode 4. * Set version to 2.6.3. + * 2005/09/26 - Jay Vosburgh + * - Removed backwards compatibility for old ifenslaves. Version 2.6.4. */ //#define BONDING_DEBUG 1 @@ -595,14 +597,7 @@ static int arp_ip_count = 0; static int bond_mode = BOND_MODE_ROUNDROBIN; static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; static int lacp_fast = 0; -static int app_abi_ver = 0; -static int orig_app_abi_ver = -1; /* This is used to save the first ABI version - * we receive from the application. Once set, - * it won't be changed, and the module will - * refuse to enslave/release interfaces if the - * command comes from an application using - * another ABI version. - */ + struct bond_parm_tbl { char *modename; int mode; @@ -1702,51 +1697,29 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de } } - if (app_abi_ver >= 1) { - /* The application is using an ABI, which requires the - * slave interface to be closed. - */ - if ((slave_dev->flags & IFF_UP)) { - printk(KERN_ERR DRV_NAME - ": Error: %s is up\n", - slave_dev->name); - res = -EPERM; - goto err_undo_flags; - } - - if (slave_dev->set_mac_address == NULL) { - printk(KERN_ERR DRV_NAME - ": Error: The slave device you specified does " - "not support setting the MAC address.\n"); - printk(KERN_ERR - "Your kernel likely does not support slave " - "devices.\n"); + /* + * Old ifenslave binaries are no longer supported. These can + * be identified with moderate accurary by the state of the slave: + * the current ifenslave will set the interface down prior to + * enslaving it; the old ifenslave will not. + */ + if ((slave_dev->flags & IFF_UP)) { + printk(KERN_ERR DRV_NAME ": %s is up. " + "This may be due to an out of date ifenslave.\n", + slave_dev->name); + res = -EPERM; + goto err_undo_flags; + } - res = -EOPNOTSUPP; - goto err_undo_flags; - } - } else { - /* The application is not using an ABI, which requires the - * slave interface to be open. - */ - if (!(slave_dev->flags & IFF_UP)) { - printk(KERN_ERR DRV_NAME - ": Error: %s is not running\n", - slave_dev->name); - res = -EINVAL; - goto err_undo_flags; - } + if (slave_dev->set_mac_address == NULL) { + printk(KERN_ERR DRV_NAME + ": Error: The slave device you specified does " + "not support setting the MAC address.\n"); + printk(KERN_ERR + "Your kernel likely does not support slave devices.\n"); - if ((bond->params.mode == BOND_MODE_8023AD) || - (bond->params.mode == BOND_MODE_TLB) || - (bond->params.mode == BOND_MODE_ALB)) { - printk(KERN_ERR DRV_NAME - ": Error: to use %s mode, you must upgrade " - "ifenslave.\n", - bond_mode_name(bond->params.mode)); - res = -EOPNOTSUPP; - goto err_undo_flags; - } + res = -EOPNOTSUPP; + goto err_undo_flags; } new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); @@ -1762,41 +1735,36 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de */ new_slave->original_flags = slave_dev->flags; - if (app_abi_ver >= 1) { - /* save slave's original ("permanent") mac address for - * modes that needs it, and for restoring it upon release, - * and then set it to the master's address - */ - memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); + /* + * Save slave's original ("permanent") mac address for modes + * that need it, and for restoring it upon release, and then + * set it to the master's address + */ + memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); - /* set slave to master's mac address - * The application already set the master's - * mac address to that of the first slave - */ - memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); - addr.sa_family = slave_dev->type; - res = dev_set_mac_address(slave_dev, &addr); - if (res) { - dprintk("Error %d calling set_mac_address\n", res); - goto err_free; - } + /* + * Set slave to master's mac address. The application already + * set the master's mac address to that of the first slave + */ + memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); + addr.sa_family = slave_dev->type; + res = dev_set_mac_address(slave_dev, &addr); + if (res) { + dprintk("Error %d calling set_mac_address\n", res); + goto err_free; + } - /* open the slave since the application closed it */ - res = dev_open(slave_dev); - if (res) { - dprintk("Openning slave %s failed\n", slave_dev->name); - goto err_restore_mac; - } + /* open the slave since the application closed it */ + res = dev_open(slave_dev); + if (res) { + dprintk("Openning slave %s failed\n", slave_dev->name); + goto err_restore_mac; } res = netdev_set_master(slave_dev, bond_dev); if (res) { dprintk("Error %d calling netdev_set_master\n", res); - if (app_abi_ver < 1) { - goto err_free; - } else { - goto err_close; - } + goto err_close; } new_slave->dev = slave_dev; @@ -1997,39 +1965,6 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de write_unlock_bh(&bond->lock); - if (app_abi_ver < 1) { - /* - * !!! This is to support old versions of ifenslave. - * We can remove this in 2.5 because our ifenslave takes - * care of this for us. - * We check to see if the master has a mac address yet. - * If not, we'll give it the mac address of our slave device. - */ - int ndx = 0; - - for (ndx = 0; ndx < bond_dev->addr_len; ndx++) { - dprintk("Checking ndx=%d of bond_dev->dev_addr\n", - ndx); - if (bond_dev->dev_addr[ndx] != 0) { - dprintk("Found non-zero byte at ndx=%d\n", - ndx); - break; - } - } - - if (ndx == bond_dev->addr_len) { - /* - * We got all the way through the address and it was - * all 0's. - */ - dprintk("%s doesn't have a MAC address yet. \n", - bond_dev->name); - dprintk("Going to give assign it from %s.\n", - slave_dev->name); - bond_sethwaddr(bond_dev, slave_dev); - } - } - printk(KERN_INFO DRV_NAME ": %s: enslaving %s as a%s interface with a%s link.\n", bond_dev->name, slave_dev->name, @@ -2227,12 +2162,10 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de /* close slave before restoring its mac address */ dev_close(slave_dev); - if (app_abi_ver >= 1) { - /* restore original ("permanent") mac address */ - memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); - addr.sa_family = slave_dev->type; - dev_set_mac_address(slave_dev, &addr); - } + /* restore original ("permanent") mac address */ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); + addr.sa_family = slave_dev->type; + dev_set_mac_address(slave_dev, &addr); /* restore the original state of the * IFF_NOARP flag that might have been @@ -2320,12 +2253,10 @@ static int bond_release_all(struct net_device *bond_dev) /* close slave before restoring its mac address */ dev_close(slave_dev); - if (app_abi_ver >= 1) { - /* restore original ("permanent") mac address*/ - memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); - addr.sa_family = slave_dev->type; - dev_set_mac_address(slave_dev, &addr); - } + /* restore original ("permanent") mac address*/ + memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); + addr.sa_family = slave_dev->type; + dev_set_mac_address(slave_dev, &addr); /* restore the original state of the IFF_NOARP flag that might have * been set by bond_set_slave_inactive_flags() @@ -2423,57 +2354,6 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi return res; } -static int bond_ethtool_ioctl(struct net_device *bond_dev, struct ifreq *ifr) -{ - struct ethtool_drvinfo info; - void __user *addr = ifr->ifr_data; - uint32_t cmd; - - if (get_user(cmd, (uint32_t __user *)addr)) { - return -EFAULT; - } - - switch (cmd) { - case ETHTOOL_GDRVINFO: - if (copy_from_user(&info, addr, sizeof(info))) { - return -EFAULT; - } - - if (strcmp(info.driver, "ifenslave") == 0) { - int new_abi_ver; - char *endptr; - - new_abi_ver = simple_strtoul(info.fw_version, - &endptr, 0); - if (*endptr) { - printk(KERN_ERR DRV_NAME - ": Error: got invalid ABI " - "version from application\n"); - - return -EINVAL; - } - - if (orig_app_abi_ver == -1) { - orig_app_abi_ver = new_abi_ver; - } - - app_abi_ver = new_abi_ver; - } - - strncpy(info.driver, DRV_NAME, 32); - strncpy(info.version, DRV_VERSION, 32); - snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); - - if (copy_to_user(addr, &info, sizeof(info))) { - return -EFAULT; - } - - return 0; - default: - return -EOPNOTSUPP; - } -} - static int bond_info_query(struct net_device *bond_dev, struct ifbond *info) { struct bonding *bond = bond_dev->priv; @@ -3442,16 +3322,11 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave seq_printf(seq, "Link Failure Count: %d\n", slave->link_failure_count); - if (app_abi_ver >= 1) { - seq_printf(seq, - "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n", - slave->perm_hwaddr[0], - slave->perm_hwaddr[1], - slave->perm_hwaddr[2], - slave->perm_hwaddr[3], - slave->perm_hwaddr[4], - slave->perm_hwaddr[5]); - } + seq_printf(seq, + "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + slave->perm_hwaddr[0], slave->perm_hwaddr[1], + slave->perm_hwaddr[2], slave->perm_hwaddr[3], + slave->perm_hwaddr[4], slave->perm_hwaddr[5]); if (bond->params.mode == BOND_MODE_8023AD) { const struct aggregator *agg @@ -4010,15 +3885,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd struct ifslave k_sinfo; struct ifslave __user *u_sinfo = NULL; struct mii_ioctl_data *mii = NULL; - int prev_abi_ver = orig_app_abi_ver; int res = 0; dprintk("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd); switch (cmd) { - case SIOCETHTOOL: - return bond_ethtool_ioctl(bond_dev, ifr); case SIOCGMIIPHY: mii = if_mii(ifr); if (!mii) { @@ -4090,21 +3962,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd return -EPERM; } - if (orig_app_abi_ver == -1) { - /* no orig_app_abi_ver was provided yet, so we'll use the - * current one from now on, even if it's 0 - */ - orig_app_abi_ver = app_abi_ver; - - } else if (orig_app_abi_ver != app_abi_ver) { - printk(KERN_ERR DRV_NAME - ": Error: already using ifenslave ABI version %d; to " - "upgrade ifenslave to version %d, you must first " - "reload bonding.\n", - orig_app_abi_ver, app_abi_ver); - return -EINVAL; - } - slave_dev = dev_get_by_name(ifr->ifr_slave); dprintk("slave_dev=%p: \n", slave_dev); @@ -4137,14 +3994,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd dev_put(slave_dev); } - if (res < 0) { - /* The ioctl failed, so there's no point in changing the - * orig_app_abi_ver. We'll restore it's value just in case - * we've changed it earlier in this function. - */ - orig_app_abi_ver = prev_abi_ver; - } - return res; } @@ -4578,9 +4427,18 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode) } } +static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, + struct ethtool_drvinfo *drvinfo) +{ + strncpy(drvinfo->driver, DRV_NAME, 32); + strncpy(drvinfo->version, DRV_VERSION, 32); + snprintf(drvinfo->fw_version, 32, "%d", BOND_ABI_VERSION); +} + static struct ethtool_ops bond_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, .get_sg = ethtool_op_get_sg, + .get_drvinfo = bond_ethtool_get_drvinfo, }; /* diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3881969..bbf9da8 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -40,8 +40,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.6.3" -#define DRV_RELDATE "June 8, 2005" +#define DRV_VERSION "2.6.4" +#define DRV_RELDATE "September 26, 2005" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" -- cgit v0.10.2 From 32b5bfab9a09b19ea9a7d902b249ebf311fd2999 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter Date: Thu, 22 Sep 2005 11:09:44 +0200 Subject: [PATCH] tulip DC21143 rev 48 10Mbit HDX fix The patch below is necessary to allow my Digital DS21143 Tulip rev 48 ethernet interface to work in a 10Mbit Half Duplex network. Without it, the driver keeps retrying other modes in an endless loop. It seems like someone already had the same problem with a rev 65 board :) Signed-off-by: Philippe De Muyter Signed-off-by: Jeff Garzik diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 5db694c..683f14b 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -172,7 +172,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5) int i; for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == dev->if_port) { - int startup = ! ((tp->chip_id == DC21143 && tp->revision == 65)); + int startup = ! ((tp->chip_id == DC21143 && (tp->revision == 48 || tp->revision == 65))); tp->cur_index = i; tulip_select_media(dev, startup); setup_done = 1; -- cgit v0.10.2 From 49a9db07abd4ac89693dbd4dcd92fcd1f30ece00 Mon Sep 17 00:00:00 2001 From: Wade Farnsworth Date: Mon, 3 Oct 2005 22:21:33 -0400 Subject: [PATCH] emac: add support for platform-specific unsupported PHY features This patch adds support to the ibm_emac driver for platform-specific unsupported PHY features. The patch attempts to determine the highest speed and duplex when autonegotiation is unsupported. Signed-off-by: Wade Farnsworth Signed-off-by: Jeff Garzik diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 0de3bb9..14e9b631 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -1875,6 +1875,9 @@ static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal) rc = -ENODEV; goto bail; } + + /* Disable any PHY features not supported by the platform */ + ep->phy_mii.def->features &= ~emacdata->phy_feat_exc; /* Setup initial PHY config & startup aneg */ if (ep->phy_mii.def->ops->init) @@ -1882,6 +1885,34 @@ static int emac_init_device(struct ocp_device *ocpdev, struct ibm_ocp_mal *mal) netif_carrier_off(ndev); if (ep->phy_mii.def->features & SUPPORTED_Autoneg) ep->want_autoneg = 1; + else { + ep->want_autoneg = 0; + + /* Select highest supported speed/duplex */ + if (ep->phy_mii.def->features & SUPPORTED_1000baseT_Full) { + ep->phy_mii.speed = SPEED_1000; + ep->phy_mii.duplex = DUPLEX_FULL; + } else if (ep->phy_mii.def->features & + SUPPORTED_1000baseT_Half) { + ep->phy_mii.speed = SPEED_1000; + ep->phy_mii.duplex = DUPLEX_HALF; + } else if (ep->phy_mii.def->features & + SUPPORTED_100baseT_Full) { + ep->phy_mii.speed = SPEED_100; + ep->phy_mii.duplex = DUPLEX_FULL; + } else if (ep->phy_mii.def->features & + SUPPORTED_100baseT_Half) { + ep->phy_mii.speed = SPEED_100; + ep->phy_mii.duplex = DUPLEX_HALF; + } else if (ep->phy_mii.def->features & + SUPPORTED_10baseT_Full) { + ep->phy_mii.speed = SPEED_10; + ep->phy_mii.duplex = DUPLEX_FULL; + } else { + ep->phy_mii.speed = SPEED_10; + ep->phy_mii.duplex = DUPLEX_HALF; + } + } emac_start_link(ep, NULL); /* read the MAC Address */ -- cgit v0.10.2 From 32fa2bfcf882f8901ca206e33b0d8975cc8e89a2 Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Sat, 10 Sep 2005 00:14:05 +1000 Subject: [PATCH] net/Kconfig: convert pocket_adapter ISA to PARPORT This patch changes pocket and parallel adaptors to depend on PARPORT instead of ISA in order to get the option in newer SuperIO based systems. Signed-off-by: Grant Coady Signed-off-by: Jeff Garzik diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2a908c4..c748b0e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1655,7 +1655,7 @@ config LAN_SAA9730 config NET_POCKET bool "Pocket and portable adapters" - depends on NET_ETHERNET && ISA + depends on NET_ETHERNET && PARPORT ---help--- Cute little network (Ethernet) devices which attach to the parallel port ("pocket adapters"), commonly used with laptops. If you have @@ -1679,7 +1679,7 @@ config NET_POCKET config ATP tristate "AT-LAN-TEC/RealTek pocket adapter support" - depends on NET_POCKET && ISA && X86 + depends on NET_POCKET && PARPORT && X86 select CRC32 ---help--- This is a network (Ethernet) device which attaches to your parallel @@ -1694,7 +1694,7 @@ config ATP config DE600 tristate "D-Link DE600 pocket adapter support" - depends on NET_POCKET && ISA + depends on NET_POCKET && PARPORT ---help--- This is a network (Ethernet) device which attaches to your parallel port. Read as well as the @@ -1709,7 +1709,7 @@ config DE600 config DE620 tristate "D-Link DE620 pocket adapter support" - depends on NET_POCKET && ISA + depends on NET_POCKET && PARPORT ---help--- This is a network (Ethernet) device which attaches to your parallel port. Read as well as the -- cgit v0.10.2 From 67974231d4354fe26aaa39a3153b5c0945b94858 Mon Sep 17 00:00:00 2001 From: Ion Badulescu Date: Mon, 3 Oct 2005 22:31:36 -0400 Subject: [netdrvr starfire] fix highmem and broken firmware issues Unfortunately, [your patch] might address the crash but doesn't address the real problem. It turns out that the problem is one of padding (the firmware cksum engine works only on 32-bit chunks, yuck), so the special casing for length == 1 wasn't sufficient anyway. This patch addresses the issue, as well the other issue of i386 + CONFIG_HIGHMEM being broken. It is pretty much the same workaround that Adaptec themselves used in their Windows driver. I have yet to check if it fixes the problem when the skb is non-linear, but this patch _will_ solve the problem for 99% of the users out there (those not using sendfile). Signed-off-by: Ion Badulescu Signed-off-by: Jeff Garzik diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 88b89dc..efdb179 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -133,14 +133,18 @@ - finally added firmware (GPL'ed by Adaptec) - removed compatibility code for 2.2.x + LK1.4.2.1 (Ion Badulescu) + - fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM + - added 32-bit padding to outgoing skb's, removed previous workaround + TODO: - fix forced speed/duplexing code (broken a long time ago, when somebody converted the driver to use the generic MII code) - fix VLAN support */ #define DRV_NAME "starfire" -#define DRV_VERSION "1.03+LK1.4.2" -#define DRV_RELDATE "January 19, 2005" +#define DRV_VERSION "1.03+LK1.4.2.1" +#define DRV_RELDATE "October 3, 2005" #include #include @@ -165,6 +169,14 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when * of length 1. If and when this is fixed, the #define below can be removed. */ #define HAS_BROKEN_FIRMWARE + +/* + * If using the broken firmware, data must be padded to the next 32-bit boundary. + */ +#ifdef HAS_BROKEN_FIRMWARE +#define PADDING_MASK 3 +#endif + /* * Define this if using the driver with the zero-copy patch */ @@ -257,9 +269,10 @@ static int full_duplex[MAX_UNITS] = {0, }; * This SUCKS. * We need a much better method to determine if dma_addr_t is 64-bit. */ -#if (defined(__i386__) && defined(CONFIG_HIGHMEM) && (LINUX_VERSION_CODE > 0x20500 || defined(CONFIG_HIGHMEM64G))) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) +#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) /* 64-bit dma_addr_t */ #define ADDR_64BITS /* This chip uses 64 bit addresses. */ +#define netdrv_addr_t u64 #define cpu_to_dma(x) cpu_to_le64(x) #define dma_to_cpu(x) le64_to_cpu(x) #define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit @@ -268,6 +281,7 @@ static int full_duplex[MAX_UNITS] = {0, }; #define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit #define RX_DESC_ADDR_SIZE RxDescAddr64bit #else /* 32-bit dma_addr_t */ +#define netdrv_addr_t u32 #define cpu_to_dma(x) cpu_to_le32(x) #define dma_to_cpu(x) le32_to_cpu(x) #define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit @@ -1333,21 +1347,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) } #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) - { - int has_bad_length = 0; - - if (skb_first_frag_len(skb) == 1) - has_bad_length = 1; - else { - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - if (skb_shinfo(skb)->frags[i].size == 1) { - has_bad_length = 1; - break; - } - } - - if (has_bad_length) - skb_checksum_help(skb, 0); + if (skb->ip_summed == CHECKSUM_HW) { + skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK); + if (skb == NULL) + return NETDEV_TX_OK; } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ @@ -2127,13 +2130,12 @@ static int __init starfire_init (void) #endif #endif -#ifndef ADDR_64BITS /* we can do this test only at run-time... sigh */ - if (sizeof(dma_addr_t) == sizeof(u64)) { - printk("This driver has not been ported to this 64-bit architecture yet\n"); + if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) { + printk("This driver has dma_addr_t issues, please send email to maintainer\n"); return -ENODEV; } -#endif /* not ADDR_64BITS */ + return pci_module_init (&starfire_driver); } -- cgit v0.10.2 From f36a29d5672c7698ffe55c7c05107ae77fa698cc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 3 Oct 2005 21:24:45 -0700 Subject: [PATCH] ieee80211: fix gfp flags type Fix implicit nocast warnings in ieee80211 code, including __nocast: net/ieee80211/ieee80211_tx.c:215:9: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index f915367..ecdf9f7 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -207,7 +207,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) } static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - unsigned int gfp_mask) + unsigned int __nocast gfp_mask) { struct ieee80211_txb *txb; int i; -- cgit v0.10.2 From 81c58732277654a51bb52832e1bc74234bb977bc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 3 Oct 2005 21:24:36 -0700 Subject: [PATCH] ns83820: fix gfp flags type Fix implicit nocast warnings in ns83820 code, including __nocast: drivers/net/ns83820.c:603:46: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 1d123d2..83334db 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -584,7 +584,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) return 0; } -static inline int rx_refill(struct net_device *ndev, unsigned int gfp) +static inline int rx_refill(struct net_device *ndev, unsigned int __nocast gfp) { struct ns83820 *dev = PRIV(ndev); unsigned i; -- cgit v0.10.2 From 832f8f0378ff1566f2a222352c7ad5df3f8d0d9d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 00:41:22 -0700 Subject: [PATCH] sungem: fix gfp flags type Fix nocast sparse warnings in sungen: drivers/net/sungem.h:1040:45: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index ff8ae5f..16edbb1 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -1035,7 +1035,8 @@ struct gem { #define ALIGNED_RX_SKB_ADDR(addr) \ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) -static __inline__ struct sk_buff *gem_alloc_skb(int size, int gfp_flags) +static __inline__ struct sk_buff *gem_alloc_skb(int size, + unsigned int __nocast gfp_flags) { struct sk_buff *skb = alloc_skb(size + 64, gfp_flags); -- cgit v0.10.2 From 18efefa9355119b4f6d9b73b074ebbf9882c37c3 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Tue, 4 Oct 2005 13:06:00 +0100 Subject: NTFS: Fix a stupid bug in __ntfs_bitmap_set_bits_in_run() which caused the count to become negative and hence we had a wild memset() scribbling all over the system's ram. Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 83f3322..de58579 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -102,6 +102,9 @@ ToDo/Notes: inode instead of a vfs inode as parameter. - Fix the definition of the CHKD ntfs record magic. It had an off by two error causing it to be CHKB instead of CHKD. + - Fix a stupid bug in __ntfs_bitmap_set_bits_in_run() which caused the + count to become negative and hence we had a wild memset() scribbling + all over the system's ram. 2.1.23 - Implement extension of resident files and make writing safe as well as many bug fixes, cleanups, and enhancements... diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c index 12cf2e3..7a190cd 100644 --- a/fs/ntfs/bitmap.c +++ b/fs/ntfs/bitmap.c @@ -1,7 +1,7 @@ /* * bitmap.c - NTFS kernel bitmap handling. Part of the Linux-NTFS project. * - * Copyright (c) 2004 Anton Altaparmakov + * Copyright (c) 2004-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -90,7 +90,8 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit, /* If the first byte is partial, modify the appropriate bits in it. */ if (bit) { u8 *byte = kaddr + pos; - while ((bit & 7) && cnt--) { + while ((bit & 7) && cnt) { + cnt--; if (value) *byte |= 1 << bit++; else -- cgit v0.10.2 From c394e458b69632902d65f9e2f39df79314f72908 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Tue, 4 Oct 2005 13:08:53 +0100 Subject: NTFS: Fix a 64-bitness bug where a left-shift could overflow a 32-bit variable which we now cast to 64-bit first (fs/ntfs/mft.c::map_mft_record_page(). Signed-off-by: Anton Altaparmakov diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 01f2dfa..5c248d4 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h @@ -309,7 +309,7 @@ typedef le16 MFT_RECORD_FLAGS; * Note: The _LE versions will return a CPU endian formatted value! */ #define MFT_REF_MASK_CPU 0x0000ffffffffffffULL -#define MFT_REF_MASK_LE const_cpu_to_le64(0x0000ffffffffffffULL) +#define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU) typedef u64 MFT_REF; typedef le64 leMFT_REF; diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 247586d..b011369 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -58,7 +58,8 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) * overflowing the unsigned long, but I don't think we would ever get * here if the volume was that big... */ - index = ni->mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; + index = (u64)ni->mft_no << vol->mft_record_size_bits >> + PAGE_CACHE_SHIFT; ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; i_size = i_size_read(mft_vi); diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c index a389a5a..0ea887f 100644 --- a/fs/ntfs/unistr.c +++ b/fs/ntfs/unistr.c @@ -1,7 +1,7 @@ /* * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published -- cgit v0.10.2 From 96f339c6b95344942fe5fce012ff4f2a3b2cb80d Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Wed, 28 Sep 2005 17:05:19 -0500 Subject: [IA64] mbcs_init() should give up unless running on sn2 CONFIG_SGI_MBCS is enabled in generic kernels, but the driver may oops some other platforms. Check whether we are running on sn2 and bail out if we are not before doing anything dangerous. Acked-by: Bruce Losure Signed-off-by: Greg Edwards Signed-off-by: Tony Luck diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 3fa64c6..c268ee0 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -830,6 +830,9 @@ static int __init mbcs_init(void) { int rv; + if (!ia64_platform_is("sn2")) + return -ENODEV; + // Put driver into chrdevs[]. Get major number. rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops); if (rv < 0) { -- cgit v0.10.2 From 87bf9c97b4b3af8dec7b2b79cdfe7bfc0a0a03b2 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 4 Oct 2005 13:00:39 -0700 Subject: [IPV6]: Fix infinite loop in udp_v6_get_port(). Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e4cad11..bf95193 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -99,7 +99,7 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) next:; } result = best; - for(;; result += UDP_HTABLE_SIZE) { + for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { if (result > sysctl_local_port_range[1]) result = sysctl_local_port_range[0] + ((result - sysctl_local_port_range[0]) & @@ -107,6 +107,8 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) if (!udp_lport_inuse(result)) break; } + if (i >= (1 << 16) / UDP_HTABLE_SIZE) + goto fail; gotit: udp_port_rover = snum = result; } else { -- cgit v0.10.2 From e6308be85afee685347fa3440bed10faaa5d6c1a Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Tue, 4 Oct 2005 13:01:58 -0700 Subject: [IPV4]: fib_trie root-node expansion The patch below introduces special thresholds to keep root node in the trie large. This gives a flatter tree at the cost of a modest memory increase. Overall it seems to be gain and this was also proposed by one the authors of the paper in recent a seminar. Main table after loading 123 k routes. Aver depth: 3.30 Max depth: 9 Root-node size 12 bits Total size: 4044 kB With the patch: Aver depth: 2.78 Max depth: 8 Root-node size 15 bits Total size: 4150 kB An increase of 8-10% was seen in forwading performance for an rDoS attack. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 50c0519..0093ea0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -286,6 +286,8 @@ static inline void check_tnode(const struct tnode *tn) static int halve_threshold = 25; static int inflate_threshold = 50; +static int halve_threshold_root = 15; +static int inflate_threshold_root = 25; static void __alias_free_mem(struct rcu_head *head) @@ -449,6 +451,8 @@ static struct node *resize(struct trie *t, struct tnode *tn) int i; int err = 0; struct tnode *old_tn; + int inflate_threshold_use; + int halve_threshold_use; if (!tn) return NULL; @@ -541,10 +545,17 @@ static struct node *resize(struct trie *t, struct tnode *tn) check_tnode(tn); + /* Keep root node larger */ + + if(!tn->parent) + inflate_threshold_use = inflate_threshold_root; + else + inflate_threshold_use = inflate_threshold; + err = 0; while ((tn->full_children > 0 && 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >= - inflate_threshold * tnode_child_length(tn))) { + inflate_threshold_use * tnode_child_length(tn))) { old_tn = tn; tn = inflate(t, tn); @@ -564,10 +575,18 @@ static struct node *resize(struct trie *t, struct tnode *tn) * node is above threshold. */ + + /* Keep root node larger */ + + if(!tn->parent) + halve_threshold_use = halve_threshold_root; + else + halve_threshold_use = halve_threshold; + err = 0; while (tn->bits > 1 && 100 * (tnode_child_length(tn) - tn->empty_children) < - halve_threshold * tnode_child_length(tn)) { + halve_threshold_use * tnode_child_length(tn)) { old_tn = tn; tn = halve(t, tn); -- cgit v0.10.2 From 433992361ce95a1da76b76c9c24d4c957b058aff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Oct 2005 17:36:04 +0100 Subject: [PATCH] missing include in megaraid_sas megaraid_sas depends on arch-specific indirect includes pulling fs.h in; on alpha they do not. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 1b3148e..c3f6373 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include -- cgit v0.10.2 From 25e2d79f527b7abce624f30516f3167195b69a2e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Oct 2005 17:40:44 +0100 Subject: [PATCH] bogus kfree() in ibmtr On several failure exits in ibmtr we end up doing kfree() on dev->priv, with dev allocated by alloc_trdev() and ->priv never reassigned. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index e7b0010..32057e6 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -531,7 +531,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) if (!time_after(jiffies, timeout)) continue; DPRINTK( "Hardware timeout during initialization.\n"); iounmap(t_mmio); - kfree(ti); return -ENODEV; } ti->sram_phys = @@ -645,7 +644,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) DPRINTK("Unknown shared ram paging info %01X\n", ti->shared_ram_paging); iounmap(t_mmio); - kfree(ti); return -ENODEV; break; } /*end switch shared_ram_paging */ @@ -675,7 +673,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) "driver limit (%05x), adapter not started.\n", chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE); iounmap(t_mmio); - kfree(ti); return -ENODEV; } else { /* seems cool, record what we have figured out */ ti->sram_base = new_base >> 12; @@ -690,7 +687,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n", irq); iounmap(t_mmio); - kfree(ti); return -ENODEV; } /*?? Now, allocate some of the PIO PORTs for this driver.. */ @@ -699,7 +695,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr) DPRINTK("Could not grab PIO range. Halting driver.\n"); free_irq(dev->irq, dev); iounmap(t_mmio); - kfree(ti); return -EBUSY; } -- cgit v0.10.2 From ce0fe7e70a0ad11097a3773e9f3f0de3d859edf0 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 4 Oct 2005 17:43:06 +0100 Subject: [PATCH] bfs endianness annotations Signed-off-by: Alexey Dobriyan Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index e240c33..5af928f 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -108,7 +108,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, inode->i_mapping->a_ops = &bfs_aops; inode->i_mode = mode; inode->i_ino = ino; - BFS_I(inode)->i_dsk_ino = cpu_to_le16(ino); + BFS_I(inode)->i_dsk_ino = ino; BFS_I(inode)->i_sblock = 0; BFS_I(inode)->i_eblock = 0; insert_inode_hash(inode); diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index c7b39aa2..868af0f2 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -357,7 +357,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) } info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ - info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - cpu_to_le32(bfs_sb->s_start))>>BFS_BSIZE_BITS; + info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS; info->si_freei = 0; info->si_lf_eblk = 0; info->si_lf_sblk = 0; diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h index c1237aa..8ed6dfdc 100644 --- a/include/linux/bfs_fs.h +++ b/include/linux/bfs_fs.h @@ -20,19 +20,19 @@ /* BFS inode layout on disk */ struct bfs_inode { - __u16 i_ino; + __le16 i_ino; __u16 i_unused; - __u32 i_sblock; - __u32 i_eblock; - __u32 i_eoffset; - __u32 i_vtype; - __u32 i_mode; - __s32 i_uid; - __s32 i_gid; - __u32 i_nlink; - __u32 i_atime; - __u32 i_mtime; - __u32 i_ctime; + __le32 i_sblock; + __le32 i_eblock; + __le32 i_eoffset; + __le32 i_vtype; + __le32 i_mode; + __le32 i_uid; + __le32 i_gid; + __le32 i_nlink; + __le32 i_atime; + __le32 i_mtime; + __le32 i_ctime; __u32 i_padding[4]; }; @@ -41,17 +41,17 @@ struct bfs_inode { #define BFS_DIRS_PER_BLOCK 32 struct bfs_dirent { - __u16 ino; + __le16 ino; char name[BFS_NAMELEN]; }; /* BFS superblock layout on disk */ struct bfs_super_block { - __u32 s_magic; - __u32 s_start; - __u32 s_end; - __s32 s_from; - __s32 s_to; + __le32 s_magic; + __le32 s_start; + __le32 s_end; + __le32 s_from; + __le32 s_to; __s32 s_bfrom; __s32 s_bto; char s_fsname[6]; @@ -66,15 +66,15 @@ struct bfs_super_block { #define BFS_INO2OFF(ino) \ ((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE) #define BFS_NZFILESIZE(ip) \ - ((cpu_to_le32((ip)->i_eoffset) + 1) - cpu_to_le32((ip)->i_sblock) * BFS_BSIZE) + ((le32_to_cpu((ip)->i_eoffset) + 1) - le32_to_cpu((ip)->i_sblock) * BFS_BSIZE) #define BFS_FILESIZE(ip) \ ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip)) #define BFS_FILEBLOCKS(ip) \ - ((ip)->i_sblock == 0 ? 0 : (cpu_to_le32((ip)->i_eblock) + 1) - cpu_to_le32((ip)->i_sblock)) + ((ip)->i_sblock == 0 ? 0 : (le32_to_cpu((ip)->i_eblock) + 1) - le32_to_cpu((ip)->i_sblock)) #define BFS_UNCLEAN(bfs_sb, sb) \ - ((cpu_to_le32(bfs_sb->s_from) != -1) && (cpu_to_le32(bfs_sb->s_to) != -1) && !(sb->s_flags & MS_RDONLY)) + ((le32_to_cpu(bfs_sb->s_from) != -1) && (le32_to_cpu(bfs_sb->s_to) != -1) && !(sb->s_flags & MS_RDONLY)) #endif /* _LINUX_BFS_FS_H */ -- cgit v0.10.2 From c2b513dfbb04d7c94cca145172cfeb91f7683e54 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 4 Oct 2005 17:48:44 +0100 Subject: [PATCH] bfs iget() abuses bfs_fill_super() walks the inode table to get the bitmap of free inodes and collect stats. It has no business using iget() for that - it's a lot of extra work, extra icache pollution and more complex code. Switched to walking the damn thing directly. Note: that also allows to kill ->i_dsk_ino in there - separate patch if Tigran can confirm that this field can be zero only for deleted inodes (i.e. something that could only be found during that scan and not by normal lookups). Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 868af0f2..3af6c73 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -362,23 +362,41 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) info->si_lf_eblk = 0; info->si_lf_sblk = 0; info->si_lf_ioff = 0; + bh = NULL; for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { - inode = iget(s,i); - if (BFS_I(inode)->i_dsk_ino == 0) + struct bfs_inode *di; + int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; + int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; + unsigned long sblock, eblock; + + if (!off) { + brelse(bh); + bh = sb_bread(s, block); + } + + if (!bh) + continue; + + di = (struct bfs_inode *)bh->b_data + off; + + if (!di->i_ino) { info->si_freei++; - else { - set_bit(i, info->si_imap); - info->si_freeb -= inode->i_blocks; - if (BFS_I(inode)->i_eblock > info->si_lf_eblk) { - info->si_lf_eblk = BFS_I(inode)->i_eblock; - info->si_lf_sblk = BFS_I(inode)->i_sblock; - info->si_lf_ioff = BFS_INO2OFF(i); - } + continue; + } + set_bit(i, info->si_imap); + info->si_freeb -= BFS_FILEBLOCKS(di); + + sblock = le32_to_cpu(di->i_sblock); + eblock = le32_to_cpu(di->i_eblock); + if (eblock > info->si_lf_eblk) { + info->si_lf_eblk = eblock; + info->si_lf_sblk = sblock; + info->si_lf_ioff = BFS_INO2OFF(i); } - iput(inode); } + brelse(bh); if (!(s->s_flags & MS_RDONLY)) { - mark_buffer_dirty(bh); + mark_buffer_dirty(info->si_sbh); s->s_dirt = 1; } dump_imap("read_super", s); -- cgit v0.10.2 From 71dc036247573e377703233af289019f4aa3176e Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Tue, 4 Oct 2005 14:53:49 -0400 Subject: [PATCH] UML - Fix Al's build tidying Al's build tidying missed one bit from me - without this UML doesn't boot. Signed-off-by: Jeff Dike Acked-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 677fc26..26b6867 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c @@ -46,7 +46,7 @@ void foo(void) OFFSET(HOST_SC_FP_ST, _fpstate, _st); OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env); - DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE); + DEFINE(HOST_FRAME_SIZE, FRAME_SIZE); DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct)); DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct)); -- cgit v0.10.2 From fad1c45c939bb246a488be1fa06f539e85b80545 Mon Sep 17 00:00:00 2001 From: Allan Graves Date: Tue, 4 Oct 2005 14:53:52 -0400 Subject: [PATCH] uml: Fix sysrq-r support for skas mode The old code had the IP and SP coming from the registers in the thread struct, which are completely wrong since those are the userspace registers. This fixes that by pulling the correct values from the jmp_buf in which the kernel state of each thread is stored. Signed-off-by: Allan Graves Signed-off-by: Jeff Dike Signed-off-by: Linus Torvalds diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 0a35e6d..4892e5f 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -15,16 +15,6 @@ extern void save_registers(int pid, union uml_pt_regs *regs); extern void restore_registers(int pid, union uml_pt_regs *regs); extern void init_registers(int pid); extern void get_safe_registers(unsigned long * regs); +extern void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 331aa2d..8f06567 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -218,10 +218,6 @@ struct syscall_args { case RBP: UPT_RBP(regs) = __upt_val; break; \ case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ case CS: UPT_CS(regs) = __upt_val; break; \ - case DS: UPT_DS(regs) = __upt_val; break; \ - case ES: UPT_ES(regs) = __upt_val; break; \ - case FS: UPT_FS(regs) = __upt_val; break; \ - case GS: UPT_GS(regs) = __upt_val; break; \ case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ default : \ panic("Bad register in UPT_SET : %d\n", reg); \ diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index f808500..b331e97 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -62,13 +62,7 @@ void show_stack(struct task_struct *task, unsigned long *esp) if (esp == NULL) { if (task != current && task != NULL) { - /* XXX: Isn't this bogus? I.e. isn't this the - * *userspace* stack of this task? If not so, use this - * even when task == current (as in i386). - */ esp = (unsigned long *) KSTK_ESP(task); - /* Which one? No actual difference - just coding style.*/ - //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs); } else { esp = (unsigned long *) &esp; } @@ -84,5 +78,5 @@ void show_stack(struct task_struct *task, unsigned long *esp) } printk("Call Trace: \n"); - show_trace(current, esp); + show_trace(task, esp); } diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 3125d32..aee4812 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -5,6 +5,7 @@ #include #include +#include #include "sysdep/ptrace_user.h" #include "sysdep/ptrace.h" #include "uml-config.h" @@ -126,13 +127,11 @@ void get_safe_registers(unsigned long *regs) memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); } -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) +{ + struct __jmp_buf_tag *jmpbuf = buffer; + + UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); + UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); + UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); +} diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index 44438d1..4b638dfb 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -5,6 +5,7 @@ #include #include +#include #include "ptrace_user.h" #include "uml-config.h" #include "skas_ptregs.h" @@ -74,13 +75,11 @@ void get_safe_registers(unsigned long *regs) memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); } -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) +{ + struct __jmp_buf_tag *jmpbuf = buffer; + + UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); + UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); + UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); +} diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c index e3706d1..d5244f0 100644 --- a/arch/um/sys-i386/sysrq.c +++ b/arch/um/sys-i386/sysrq.c @@ -88,9 +88,7 @@ void show_trace(struct task_struct* task, unsigned long * stack) task = current; if (task != current) { - //ebp = (unsigned long) KSTK_EBP(task); - /* Which one? No actual difference - just coding style.*/ - ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs); + ebp = (unsigned long) KSTK_EBP(task); } else { asm ("movl %%ebp, %0" : "=r" (ebp) : ); } @@ -99,15 +97,6 @@ void show_trace(struct task_struct* task, unsigned long * stack) ((unsigned long)stack & (~(THREAD_SIZE - 1))); print_context_stack(context, stack, ebp); - /*while (((long) stack & (THREAD_SIZE-1)) != 0) { - addr = *stack; - if (__kernel_text_address(addr)) { - printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); - print_symbol(" %s", addr); - printk("\n"); - } - stack++; - }*/ printk("\n"); } diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index 2d24236..075771c 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h @@ -13,6 +13,7 @@ struct task_struct; #include "linux/config.h" #include "asm/ptrace.h" #include "choose-mode.h" +#include "registers.h" struct mm_struct; @@ -136,19 +137,15 @@ extern struct cpuinfo_um cpu_data[]; #define current_cpu_data boot_cpu_data #endif -#define KSTK_EIP(tsk) (PT_REGS_IP(&tsk->thread.regs)) -#define KSTK_ESP(tsk) (PT_REGS_SP(&tsk->thread.regs)) -#define get_wchan(p) (0) +#ifdef CONFIG_MODE_SKAS +#define KSTK_REG(tsk, reg) \ + ({ union uml_pt_regs regs; \ + get_thread_regs(®s, tsk->thread.mode.skas.switch_buf); \ + UPT_REG(®s, reg); }) +#else +#define KSTK_REG(tsk, reg) (0xbadbabe) #endif +#define get_wchan(p) (0) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ +#endif diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h index 431bad3..4108a57 100644 --- a/include/asm-um/processor-i386.h +++ b/include/asm-um/processor-i386.h @@ -43,17 +43,10 @@ static inline void rep_nop(void) #define ARCH_IS_STACKGROW(address) \ (address + 32 >= UPT_SP(¤t->thread.regs.regs)) +#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP) +#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP) +#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP) + #include "asm/processor-generic.h" #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h index 0beb9a4..e1e1255 100644 --- a/include/asm-um/processor-x86_64.h +++ b/include/asm-um/processor-x86_64.h @@ -36,17 +36,9 @@ extern inline void rep_nop(void) #define ARCH_IS_STACKGROW(address) \ (address + 128 >= UPT_SP(¤t->thread.regs.regs)) +#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP) +#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP) + #include "asm/processor-generic.h" #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ -- cgit v0.10.2 From d78795b6930956fb66238d4d26242482d4a31470 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 4 Oct 2005 23:17:51 +0100 Subject: [ARM] 2949/1: Hynix h720x Run mode Patch from Sascha Hauer After coming out of idle mode the h720x goes into slow mode. Switch it back to run mode. Signed-off-by: Sascha Hauer Signed-off-by: Russell King diff --git a/include/asm-arm/arch-h720x/system.h b/include/asm-arm/arch-h720x/system.h index 0b025e2..09eda84 100644 --- a/include/asm-arm/arch-h720x/system.h +++ b/include/asm-arm/arch-h720x/system.h @@ -17,9 +17,11 @@ static void arch_idle(void) { CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_IDLE; - __asm__ __volatile__( - "mov r0, r0\n\t" - "mov r0, r0"); + nop(); + nop(); + CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_RUN; + nop(); + nop(); } -- cgit v0.10.2 From 0a5b0aa8a331f4346b4b02bc653107304a6abdc5 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 4 Oct 2005 23:17:52 +0100 Subject: [ARM] 2950/1: i.MX gpio setup function Patch from Sascha Hauer Current implementation of imx_gpio_mode does not allow to configure all alternate routing possibilities of the i.MX. With this patch every bit in the gpio setup registers has a corresponding bit in the gpio_mode parameter, so every routing should be possible now. Signed-off-by: Sascha Hauer Signed-off-by: Russell King diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index 41e5849..f8a742b 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c @@ -28,14 +28,15 @@ #include #include #include +#include #include void imx_gpio_mode(int gpio_mode) { unsigned int pin = gpio_mode & GPIO_PIN_MASK; - unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5; - unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; unsigned int tmp; /* Pullup enable */ @@ -57,7 +58,7 @@ void imx_gpio_mode(int gpio_mode) GPR(port) &= ~(1<> GPIO_AOUT_SHIFT) & 3) << (pin * 2); + ICONFB1(port) &= ~( 3<<(pin*2)); + ICONFB1(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2); } else { tmp = OCR2(port); tmp &= ~( 3<<((pin-16)*2)); tmp |= (ocr << ((pin-16)*2)); OCR2(port) = tmp; - if( gpio_mode & GPIO_AOUT ) - ICONFA2(port) &= ~( 3<<((pin-16)*2)); - if( gpio_mode & GPIO_BOUT ) - ICONFB2(port) &= ~( 3<<((pin-16)*2)); + ICONFA2(port) &= ~( 3<<((pin-16)*2)); + ICONFA2(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << ((pin-16) * 2); + ICONFB2(port) &= ~( 3<<((pin-16)*2)); + ICONFB2(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << ((pin-16) * 2); } } diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c index 5d25434..a7511dd 100644 --- a/arch/arm/mach-imx/mx1ads.c +++ b/arch/arm/mach-imx/mx1ads.c @@ -55,7 +55,7 @@ static void __init mx1ads_init(void) { #ifdef CONFIG_LEDS - imx_gpio_mode(GPIO_PORTA | GPIO_OUT | GPIO_GPIO | 2); + imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2); #endif platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h index 93b840e..229f700 100644 --- a/include/asm-arm/arch-imx/imx-regs.h +++ b/include/asm-arm/arch-imx/imx-regs.h @@ -76,6 +76,7 @@ #define GPIO_PIN_MASK 0x1f #define GPIO_PORT_MASK (0x3 << 5) +#define GPIO_PORT_SHIFT 5 #define GPIO_PORTA (0<<5) #define GPIO_PORTB (1<<5) #define GPIO_PORTC (2<<5) @@ -88,24 +89,37 @@ #define GPIO_PF (0<<9) #define GPIO_AF (1<<9) +#define GPIO_OCR_SHIFT 10 #define GPIO_OCR_MASK (3<<10) #define GPIO_AIN (0<<10) #define GPIO_BIN (1<<10) #define GPIO_CIN (2<<10) -#define GPIO_GPIO (3<<10) +#define GPIO_DR (3<<10) -#define GPIO_AOUT (1<<12) -#define GPIO_BOUT (1<<13) +#define GPIO_AOUT_SHIFT 12 +#define GPIO_AOUT_MASK (3<<12) +#define GPIO_AOUT (0<<12) +#define GPIO_AOUT_ISR (1<<12) +#define GPIO_AOUT_0 (2<<12) +#define GPIO_AOUT_1 (3<<12) + +#define GPIO_BOUT_SHIFT 14 +#define GPIO_BOUT_MASK (3<<14) +#define GPIO_BOUT (0<<14) +#define GPIO_BOUT_ISR (1<<14) +#define GPIO_BOUT_0 (2<<14) +#define GPIO_BOUT_1 (3<<14) + +#define GPIO_GIUS (1<<16) /* assignements for GPIO alternate/primary functions */ /* FIXME: This list is not completed. The correct directions are * missing on some (many) pins */ -#define PA0_PF_A24 ( GPIO_PORTA | GPIO_PF | 0 ) -#define PA0_AIN_SPI2_CLK ( GPIO_PORTA | GPIO_OUT | GPIO_AIN | 0 ) +#define PA0_AIN_SPI2_CLK ( GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 0 ) #define PA0_AF_ETMTRACESYNC ( GPIO_PORTA | GPIO_AF | 0 ) -#define PA1_AOUT_SPI2_RXD ( GPIO_PORTA | GPIO_IN | GPIO_AOUT | 1 ) +#define PA1_AOUT_SPI2_RXD ( GPIO_GIUS | GPIO_PORTA | GPIO_IN | 1 ) #define PA1_PF_TIN ( GPIO_PORTA | GPIO_PF | 1 ) #define PA2_PF_PWM0 ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 2 ) #define PA3_PF_CSI_MCLK ( GPIO_PORTA | GPIO_PF | 3 ) @@ -123,7 +137,7 @@ #define PA15_PF_I2C_SDA ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 15 ) #define PA16_PF_I2C_SCL ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 16 ) #define PA17_AF_ETMTRACEPKT4 ( GPIO_PORTA | GPIO_AF | 17 ) -#define PA17_AIN_SPI2_SS ( GPIO_PORTA | GPIO_AIN | 17 ) +#define PA17_AIN_SPI2_SS ( GPIO_GIUS | GPIO_PORTA | GPIO_OUT | 17 ) #define PA18_AF_ETMTRACEPKT5 ( GPIO_PORTA | GPIO_AF | 18 ) #define PA19_AF_ETMTRACEPKT6 ( GPIO_PORTA | GPIO_AF | 19 ) #define PA20_AF_ETMTRACEPKT7 ( GPIO_PORTA | GPIO_AF | 20 ) @@ -191,19 +205,27 @@ #define PC15_PF_SPI1_SS ( GPIO_PORTC | GPIO_PF | 15 ) #define PC16_PF_SPI1_MISO ( GPIO_PORTC | GPIO_PF | 16 ) #define PC17_PF_SPI1_MOSI ( GPIO_PORTC | GPIO_PF | 17 ) +#define PC24_BIN_UART3_RI ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24 ) +#define PC25_BIN_UART3_DSR ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25 ) +#define PC26_AOUT_UART3_DTR ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 26 ) +#define PC27_BIN_UART3_DCD ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27 ) +#define PC28_BIN_UART3_CTS ( GPIO_GIUS | GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28 ) +#define PC29_AOUT_UART3_RTS ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 29 ) +#define PC30_BIN_UART3_TX ( GPIO_GIUS | GPIO_PORTC | GPIO_BIN | 30 ) +#define PC31_AOUT_UART3_RX ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 31) #define PD6_PF_LSCLK ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 6 ) #define PD7_PF_REV ( GPIO_PORTD | GPIO_PF | 7 ) #define PD7_AF_UART2_DTR ( GPIO_PORTD | GPIO_IN | GPIO_AF | 7 ) -#define PD7_AIN_SPI2_SCLK ( GPIO_PORTD | GPIO_AIN | 7 ) +#define PD7_AIN_SPI2_SCLK ( GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 7 ) #define PD8_PF_CLS ( GPIO_PORTD | GPIO_PF | 8 ) #define PD8_AF_UART2_DCD ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 8 ) -#define PD8_AIN_SPI2_SS ( GPIO_PORTD | GPIO_AIN | 8 ) +#define PD8_AIN_SPI2_SS ( GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 8 ) #define PD9_PF_PS ( GPIO_PORTD | GPIO_PF | 9 ) #define PD9_AF_UART2_RI ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 9 ) -#define PD9_AOUT_SPI2_RXD ( GPIO_PORTD | GPIO_IN | GPIO_AOUT | 9 ) +#define PD9_AOUT_SPI2_RXD ( GPIO_GIUS | GPIO_PORTD | GPIO_IN | 9 ) #define PD10_PF_SPL_SPR ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 10 ) #define PD10_AF_UART2_DSR ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 10 ) -#define PD10_AIN_SPI2_TXD ( GPIO_PORTD | GPIO_OUT | GPIO_AIN | 10 ) +#define PD10_AIN_SPI2_TXD ( GPIO_GIUS | GPIO_PORTD | GPIO_OUT | 10 ) #define PD11_PF_CONTRAST ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 11 ) #define PD12_PF_ACD_OE ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 12 ) #define PD13_PF_LP_HSYNC ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 13 ) @@ -225,7 +247,7 @@ #define PD29_PF_LD14 ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 29 ) #define PD30_PF_LD15 ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 30 ) #define PD31_PF_TMR2OUT ( GPIO_PORTD | GPIO_PF | 31 ) -#define PD31_BIN_SPI2_TXD ( GPIO_PORTD | GPIO_BIN | 31 ) +#define PD31_BIN_SPI2_TXD ( GPIO_GIUS | GPIO_PORTD | GPIO_BIN | 31 ) /* * PWM controller -- cgit v0.10.2 From 74f8849496b73d2ae4f9c53f61bf59e063ceed88 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 4 Oct 2005 23:17:52 +0100 Subject: [ARM] 2951/1: fix wrong comment Patch from Nicolas Pitre The cmpxchg emulation syscall needs write access. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index e7d22db..f6de76e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -504,7 +504,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) bad_access: spin_unlock(&mm->page_table_lock); - /* simulate a read access fault */ + /* simulate a write access fault */ do_DataAbort(addr, 15 + (1 << 11), regs); return -1; } -- cgit v0.10.2 From c2f480869fa7559fa3532e415e3e3ec49339f208 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 4 Oct 2005 23:17:53 +0100 Subject: [ARM] 2952/1: fix a register clobber list Patch from Nicolas Pitre If gcc decides to assign lr to %0 we're screwed. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 42629ff..ea569ba 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -305,7 +305,7 @@ long execve(const char *filename, char **argv, char **envp) "Ir" (THREAD_START_SP - sizeof(regs)), "r" (®s), "Ir" (sizeof(regs)) - : "r0", "r1", "r2", "r3", "ip", "memory"); + : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); out: return ret; -- cgit v0.10.2 From 0835ae0f27c0bfde67613d189ef6c537e004a6de Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 4 Oct 2005 15:23:20 -0700 Subject: [SPARC64]: Replace cheetah+ code patching with variables. Instead of code patching to handle the page size fields in the context registers, just use variables from which we get the proper values. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 2879b10..f685035dbd 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -97,8 +97,8 @@ do_fpdis: faddd %f0, %f2, %f4 fmuld %f0, %f2, %f6 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_1: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS + 0xc0, %g2 @@ -126,8 +126,8 @@ cplus_fptrap_insn_1: fzero %f34 ldxa [%g3] ASI_DMMU, %g5 add %g6, TI_FPREGS, %g1 -cplus_fptrap_insn_2: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS + 0x40, %g2 @@ -153,8 +153,8 @@ cplus_fptrap_insn_2: 3: mov SECONDARY_CONTEXT, %g3 add %g6, TI_FPREGS, %g1 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_3: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync mov 0x40, %g2 @@ -319,8 +319,8 @@ do_fptrap_after_fsr: stx %g3, [%g6 + TI_GSR] mov SECONDARY_CONTEXT, %g3 ldxa [%g3] ASI_DMMU, %g5 -cplus_fptrap_insn_4: - sethi %hi(0), %g2 + sethi %hi(sparc64_kern_sec_context), %g2 + ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2 stxa %g2, [%g3] ASI_DMMU membar #Sync add %g6, TI_FPREGS, %g2 @@ -341,33 +341,6 @@ cplus_fptrap_insn_4: ba,pt %xcc, etrap wr %g0, 0, %fprs -cplus_fptrap_1: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - - .globl cheetah_plus_patch_fpdis -cheetah_plus_patch_fpdis: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_fptrap_1), %o0 - lduw [%o0 + %lo(cplus_fptrap_1)], %o1 - - set cplus_fptrap_insn_1, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_2, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_3, %o2 - stw %o1, [%o2] - flush %o2 - set cplus_fptrap_insn_4, %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop - /* The registers for cross calls will be: * * DATA 0: [low 32-bits] Address of function to call, jmp to this diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 50d2af1..0d8eba2 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -68,12 +68,8 @@ etrap_irq: wrpr %g3, 0, %otherwin wrpr %g2, 0, %wstate -cplus_etrap_insn_1: - sethi %hi(0), %g3 - sllx %g3, 32, %g3 -cplus_etrap_insn_2: - sethi %hi(0), %g2 - or %g3, %g2, %g3 + sethi %hi(sparc64_kern_pri_context), %g2 + ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 stxa %g3, [%l4] ASI_DMMU flush %l6 wr %g0, ASI_AIUS, %asi @@ -215,12 +211,8 @@ scetrap: rdpr %pil, %g2 mov PRIMARY_CONTEXT, %l4 wrpr %g3, 0, %otherwin wrpr %g2, 0, %wstate -cplus_etrap_insn_3: - sethi %hi(0), %g3 - sllx %g3, 32, %g3 -cplus_etrap_insn_4: - sethi %hi(0), %g2 - or %g3, %g2, %g3 + sethi %hi(sparc64_kern_pri_context), %g2 + ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3 stxa %g3, [%l4] ASI_DMMU flush %l6 @@ -264,38 +256,3 @@ cplus_etrap_insn_4: #undef TASK_REGOFF #undef ETRAP_PSTATE1 - -cplus_einsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 -cplus_einsn_2: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - - .globl cheetah_plus_patch_etrap -cheetah_plus_patch_etrap: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_einsn_1), %o0 - sethi %hi(cplus_etrap_insn_1), %o2 - lduw [%o0 + %lo(cplus_einsn_1)], %o1 - or %o2, %lo(cplus_etrap_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - sethi %hi(cplus_etrap_insn_3), %o2 - or %o2, %lo(cplus_etrap_insn_3), %o2 - stw %o1, [%o2] - flush %o2 - - sethi %hi(cplus_einsn_2), %o0 - sethi %hi(cplus_etrap_insn_2), %o2 - lduw [%o0 + %lo(cplus_einsn_2)], %o1 - or %o2, %lo(cplus_etrap_insn_2), %o2 - stw %o1, [%o2] - flush %o2 - sethi %hi(cplus_etrap_insn_4), %o2 - or %o2, %lo(cplus_etrap_insn_4), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 89406f9..2434049 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -325,23 +325,7 @@ cheetah_tlb_fixup: 1: sethi %hi(tlb_type), %g1 stw %g2, [%g1 + %lo(tlb_type)] - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f) - ba,pt %xcc, 2f - nop - -1: /* Patch context register writes to support nucleus page - * size correctly. - */ - call cheetah_plus_patch_etrap - nop - call cheetah_plus_patch_rtrap - nop - call cheetah_plus_patch_fpdis - nop - call cheetah_plus_patch_winfixup - nop - -2: /* Patch copy/page operations to cheetah optimized versions. */ + /* Patch copy/page operations to cheetah optimized versions. */ call cheetah_patch_copyops nop call cheetah_patch_copy_page @@ -484,20 +468,13 @@ spitfire_vpte_base: call prom_set_trap_table sethi %hi(sparc64_ttable_tl0), %o0 - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) - ba,pt %xcc, 2f - nop - -1: /* Start using proper page size encodings in ctx register. */ - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 + /* Start using proper page size encodings in ctx register. */ + sethi %hi(sparc64_kern_pri_context), %g3 + ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 mov PRIMARY_CONTEXT, %g1 - sllx %g3, 32, %g3 - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - or %g3, %g2, %g3 - stxa %g3, [%g1] ASI_DMMU + stxa %g2, [%g1] ASI_DMMU membar #Sync -2: rdpr %pstate, %o1 or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index fafd227..ecfb42a 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -256,9 +256,8 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 ldxa [%l7 + %l7] ASI_DMMU, %l0 -cplus_rtrap_insn_1: - sethi %hi(0), %l1 - sllx %l1, 32, %l1 + sethi %hi(sparc64_kern_pri_nuc_bits), %l1 + ldx [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1 or %l0, %l1, %l0 stxa %l0, [%l7] ASI_DMMU flush %g6 @@ -345,21 +344,3 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5 wr %g0, FPRS_DU, %fprs ba,pt %xcc, rt_continue stb %l5, [%g6 + TI_FPDEPTH] - -cplus_rinsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 - - .globl cheetah_plus_patch_rtrap -cheetah_plus_patch_rtrap: - /* We configure the dTLB512_0 for 4MB pages and the - * dTLB512_1 for 8K pages when in context zero. - */ - sethi %hi(cplus_rinsn_1), %o0 - sethi %hi(cplus_rtrap_insn_1), %o2 - lduw [%o0 + %lo(cplus_rinsn_1)], %o1 - or %o2, %lo(cplus_rtrap_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 4c9c8f2..c1f3423 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -187,17 +187,13 @@ int prom_callback(long *args) } if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { - unsigned long kernel_pctx = 0; - - if (tlb_type == cheetah_plus) - kernel_pctx |= (CTX_CHEETAH_PLUS_NUC | - CTX_CHEETAH_PLUS_CTX0); + extern unsigned long sparc64_kern_pri_context; /* Spitfire Errata #32 workaround */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ - : "r" (kernel_pctx), + : "r" (sparc64_kern_pri_context), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 89f2fcf..9478551 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -336,20 +336,13 @@ do_unlock: call init_irqwork_curcpu nop - BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f) - ba,pt %xcc, 2f - nop - -1: /* Start using proper page size encodings in ctx register. */ - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %g3 + /* Start using proper page size encodings in ctx register. */ + sethi %hi(sparc64_kern_pri_context), %g3 + ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 mov PRIMARY_CONTEXT, %g1 - sllx %g3, 32, %g3 - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - or %g3, %g2, %g3 - stxa %g3, [%g1] ASI_DMMU + stxa %g2, [%g1] ASI_DMMU membar #Sync -2: rdpr %pstate, %o1 or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S index 99c809a..3916092 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc64/kernel/winfixup.S @@ -16,23 +16,14 @@ .text set_pcontext: -cplus_winfixup_insn_1: - sethi %hi(0), %l1 + sethi %hi(sparc64_kern_pri_context), %l1 + ldx [%l1 + %lo(sparc64_kern_pri_context)], %l1 mov PRIMARY_CONTEXT, %g1 - sllx %l1, 32, %l1 -cplus_winfixup_insn_2: - sethi %hi(0), %g2 - or %l1, %g2, %l1 stxa %l1, [%g1] ASI_DMMU flush %g6 retl nop -cplus_wfinsn_1: - sethi %uhi(CTX_CHEETAH_PLUS_NUC), %l1 -cplus_wfinsn_2: - sethi %hi(CTX_CHEETAH_PLUS_CTX0), %g2 - .align 32 /* Here are the rules, pay attention. @@ -395,23 +386,3 @@ window_dax_from_user_common: add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap clr %l6 - - - .globl cheetah_plus_patch_winfixup -cheetah_plus_patch_winfixup: - sethi %hi(cplus_wfinsn_1), %o0 - sethi %hi(cplus_winfixup_insn_1), %o2 - lduw [%o0 + %lo(cplus_wfinsn_1)], %o1 - or %o2, %lo(cplus_winfixup_insn_1), %o2 - stw %o1, [%o2] - flush %o2 - - sethi %hi(cplus_wfinsn_2), %o0 - sethi %hi(cplus_winfixup_insn_2), %o2 - lduw [%o0 + %lo(cplus_wfinsn_2)], %o1 - or %o2, %lo(cplus_winfixup_insn_2), %o2 - stw %o1, [%o2] - flush %o2 - - retl - nop diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 5db5052..4e2f71e 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -133,6 +133,12 @@ extern unsigned int sparc_ramdisk_size; struct page *mem_map_zero __read_mostly; +unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly; + +unsigned long sparc64_kern_pri_context __read_mostly; +unsigned long sparc64_kern_pri_nuc_bits __read_mostly; +unsigned long sparc64_kern_sec_context __read_mostly; + int bigkernel = 0; /* XXX Tune this... */ @@ -582,13 +588,21 @@ static void __init remap_kernel(void) prom_dtlb_load(tlb_ent, tte_data, tte_vaddr); prom_itlb_load(tlb_ent, tte_data, tte_vaddr); if (bigkernel) { - prom_dtlb_load(tlb_ent - 1, + tlb_ent -= 1; + prom_dtlb_load(tlb_ent, tte_data + 0x400000, tte_vaddr + 0x400000); - prom_itlb_load(tlb_ent - 1, + prom_itlb_load(tlb_ent, tte_data + 0x400000, tte_vaddr + 0x400000); } + sparc64_highest_unlocked_tlb_ent = tlb_ent - 1; + if (tlb_type == cheetah_plus) { + sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 | + CTX_CHEETAH_PLUS_NUC); + sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC; + sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0; + } } static void __init inherit_prom_mappings(void) @@ -788,8 +802,8 @@ void inherit_locked_prom_mappings(int save_p) } } if (tlb_type == spitfire) { - int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel; - for (i = 0; i < high; i++) { + int high = sparc64_highest_unlocked_tlb_ent; + for (i = 0; i <= high; i++) { unsigned long data; /* Spitfire Errata #32 workaround */ @@ -877,9 +891,9 @@ void inherit_locked_prom_mappings(int save_p) } } } else if (tlb_type == cheetah || tlb_type == cheetah_plus) { - int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel; + int high = sparc64_highest_unlocked_tlb_ent; - for (i = 0; i < high; i++) { + for (i = 0; i <= high; i++) { unsigned long data; data = cheetah_get_ldtlb_data(i); -- cgit v0.10.2 From 6d2553612fa329979e6423a5f2410fd7be5aa902 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 4 Oct 2005 15:55:51 -0700 Subject: [INET]: Shrink struct inet_ehash_bucket on 32 bits UP No need to align struct inet_ehash_bucket on a 8 bytes boundary. On 32 bits Uniprocessor, that's a waste of 4 bytes per struct (50 %) On other platforms, the attribute is useless, natual alignement is already 8. platform | Size before | Size after patch -------------+-------------+------------------ 32 bits, UP | 8 | 4 32 bits, SMP | 8 | 8 64 bits, UP | 8 | 8 64 bits, SMP | 16 | 16 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 35f49e6..f50f959 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -40,7 +40,7 @@ struct inet_ehash_bucket { rwlock_t lock; struct hlist_head chain; -} __attribute__((__aligned__(8))); +}; /* There are a few simple rules, which allow for local port reuse by * an application. In essence: -- cgit v0.10.2 From 944d2647dded12e2b05ad8ebc020644bb1997ce1 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 5 Oct 2005 00:21:39 +0200 Subject: [PATCH] x86_64: Drop global bit from early low mappings Drop global bit from early low mappings Suggested by Linus, originally also proposed by Suresh. This fixes a race condition with early start of udev, originally tracked down by Suresh B. Siddha. The problem was that switching to the user space VM would not clear the global low mappings for the beginning of memory, which lead to memory corruption. Drop the global bits. The kernel mapping stays global because it should stay constant. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 4592bf2..b92e5f4 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -270,26 +270,26 @@ ENTRY(level3_kernel_pgt) .org 0x4000 ENTRY(level2_ident_pgt) /* 40MB for bootup. */ - .quad 0x0000000000000183 - .quad 0x0000000000200183 - .quad 0x0000000000400183 - .quad 0x0000000000600183 - .quad 0x0000000000800183 - .quad 0x0000000000A00183 - .quad 0x0000000000C00183 - .quad 0x0000000000E00183 - .quad 0x0000000001000183 - .quad 0x0000000001200183 - .quad 0x0000000001400183 - .quad 0x0000000001600183 - .quad 0x0000000001800183 - .quad 0x0000000001A00183 - .quad 0x0000000001C00183 - .quad 0x0000000001E00183 - .quad 0x0000000002000183 - .quad 0x0000000002200183 - .quad 0x0000000002400183 - .quad 0x0000000002600183 + .quad 0x0000000000000083 + .quad 0x0000000000200083 + .quad 0x0000000000400083 + .quad 0x0000000000600083 + .quad 0x0000000000800083 + .quad 0x0000000000A00083 + .quad 0x0000000000C00083 + .quad 0x0000000000E00083 + .quad 0x0000000001000083 + .quad 0x0000000001200083 + .quad 0x0000000001400083 + .quad 0x0000000001600083 + .quad 0x0000000001800083 + .quad 0x0000000001A00083 + .quad 0x0000000001C00083 + .quad 0x0000000001E00083 + .quad 0x0000000002000083 + .quad 0x0000000002200083 + .quad 0x0000000002400083 + .quad 0x0000000002600083 /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */ .globl temp_boot_pmds temp_boot_pmds: -- cgit v0.10.2 From a5181ab06ddca8071b4eb54ac2c314f7d24825d4 Mon Sep 17 00:00:00 2001 From: "Horst H. von Brand" Date: Tue, 4 Oct 2005 15:58:56 -0700 Subject: [NETFILTER]: Fix Kconfig typo Signed-off-by: Horst H. von Brand Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 2cd7e7d..a765972 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -141,7 +141,7 @@ config IP_NF_PPTP tristate 'PPTP protocol support' help This module adds support for PPTP (Point to Point Tunnelling - Protocol, RFC2637) conncection tracking and NAT. + Protocol, RFC2637) connection tracking and NAT. If you are running PPTP sessions over a stateful firewall or NAT box, you may want to enable this feature. -- cgit v0.10.2 From ce12467d44d7394731ec9e91e032d50b04e502f6 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Tue, 4 Oct 2005 16:32:38 -0700 Subject: [PATCH] Fix broken IXP4xx GPIO macro Macro ended up backwards during one of cleanups. Found by Alessandro Zummo. Signed-off-by: Deepak Saxena Signed-off-by: Linus Torvalds diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index d13ee7f..f14ed63 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h @@ -93,7 +93,7 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); static inline void gpio_line_config(u8 line, u32 direction) { - if (direction == IXP4XX_GPIO_OUT) + if (direction == IXP4XX_GPIO_IN) *IXP4XX_GPIO_GPOER |= (1 << line); else *IXP4XX_GPIO_GPOER &= ~(1 << line); -- cgit v0.10.2 From 9bc39bec87ee3e35897fe27441e979e7c208f624 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 4 Oct 2005 21:33:10 -0400 Subject: [PATCH] orinoco: Information leakage due to incorrect padding The orinoco driver can send uninitialized data exposing random pieces of the system memory. This happens because data is not padded with zeroes when its length needs to be increased. Reported by Meder Kydyraliev Signed-off-by: Pavel Roskin Signed-off-by: Jeff Garzik diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 6deb7cc..cf3daaa 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -503,9 +503,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ - len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); + /* Check packet length, pad short packets, round up odd length */ + len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN); + if (skb->len < len) { + skb = skb_padto(skb, len); + if (skb == NULL) + goto fail; + } + len -= ETH_HLEN; eh = (struct ethhdr *)skb->data; @@ -557,8 +562,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) p = skb->data; } - /* Round up for odd length packets */ - err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2), + err = hermes_bap_pwrite(hw, USER_BAP, p, data_len, txfid, data_off); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", -- cgit v0.10.2 From 7b5b3f3d826ea87c224c66de9c95c09e7f110ecd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:38:44 -0700 Subject: [ATM]: fix sparse gfp nocast warnings Fix implicit nocast warnings in atm code: net/atm/atm_misc.c:35:44: warning: implicit cast to nocast type drivers/atm/fore200e.c:183:33: warning: implicit cast to nocast type Also use kzalloc() instead of kmalloc(). Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 2bf723a..6f1a83c 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -178,14 +178,12 @@ fore200e_irq_itoa(int irq) static void* -fore200e_kmalloc(int size, int flags) +fore200e_kmalloc(int size, unsigned int __nocast flags) { - void* chunk = kmalloc(size, flags); + void *chunk = kzalloc(size, flags); - if (chunk) - memset(chunk, 0x00, size); - else - printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags); + if (!chunk) + printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags); return chunk; } diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 9f374cf..f1fd849 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -457,7 +457,7 @@ static inline void atm_dev_put(struct atm_dev *dev) int atm_charge(struct atm_vcc *vcc,int truesize); struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, - int gfp_flags); + unsigned int __nocast gfp_flags); int atm_pcr_goal(struct atm_trafprm *tp); void vcc_release_async(struct atm_vcc *vcc, int reply); diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index b2113c3..71abc99 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c @@ -25,7 +25,7 @@ int atm_charge(struct atm_vcc *vcc,int truesize) struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, - int gfp_flags) + unsigned int __nocast gfp_flags) { struct sock *sk = sk_atm(vcc); int guess = atm_guess_pdu2truesize(pdu_size); -- cgit v0.10.2 From de54f3907d2f5d8e25cfafe513811f146b250dee Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:39:41 -0700 Subject: [BONDING]: fix sparse gfp nocast warnings Fix implicit nocast warnings in bonding code: drivers/net/bonding/bond_main.c:1302:49: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index fd62e43..f0a5b77 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1289,12 +1289,13 @@ static void bond_mc_list_destroy(struct bonding *bond) /* * Copy all the Multicast addresses from src to the bonding device dst */ -static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, int gpf_flag) +static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, + unsigned int __nocast gfp_flag) { struct dev_mc_list *dmi, *new_dmi; for (dmi = mc_list; dmi; dmi = dmi->next) { - new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag); + new_dmi = kmalloc(sizeof(struct dev_mc_list), gfp_flag); if (!new_dmi) { /* FIXME: Potential memory leak !!! */ -- cgit v0.10.2 From 17b698856328a42d5874ac87640e2cd84a824eef Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:41:16 -0700 Subject: [CONNECTOR]: fix sparse gfp nocast warnings Fix implicit nocast warnings in connector code: drivers/connector/connector.c:102:24: warning: implicit cast to nocast type drivers/connector/connector.c:114:45: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index bb0b3a8..1422285 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -69,7 +69,8 @@ int cn_already_initialized = 0; * a new message. * */ -int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask) +int cn_netlink_send(struct cn_msg *msg, u32 __group, + unsigned int __nocast gfp_mask) { struct cn_callback_entry *__cbq; unsigned int size; diff --git a/include/linux/connector.h b/include/linux/connector.h index 86d4b0a..96582c9 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -149,7 +149,7 @@ struct cn_dev { int cn_add_callback(struct cb_id *, char *, void (*callback) (void *)); void cn_del_callback(struct cb_id *); -int cn_netlink_send(struct cn_msg *, u32, int); +int cn_netlink_send(struct cn_msg *, u32, unsigned int __nocast); int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)); void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id); -- cgit v0.10.2 From f4a19a56e38442e434b8809915d756469f1e89a2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:41:48 -0700 Subject: [DECNET]: fix sparse gfp nocast warnings Fix implicit nocast warnings in decnet code: net/decnet/af_decnet.c:458:40: warning: implicit cast to nocast type net/decnet/dn_nsp_out.c:125:35: warning: implicit cast to nocast type net/decnet/dn_nsp_out.c:219:29: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h index 6bbeafa..8a0891e 100644 --- a/include/net/dn_nsp.h +++ b/include/net/dn_nsp.h @@ -19,9 +19,9 @@ extern void dn_nsp_send_data_ack(struct sock *sk); extern void dn_nsp_send_oth_ack(struct sock *sk); extern void dn_nsp_delayed_ack(struct sock *sk); extern void dn_send_conn_ack(struct sock *sk); -extern void dn_send_conn_conf(struct sock *sk, int gfp); +extern void dn_send_conn_conf(struct sock *sk, unsigned int __nocast gfp); extern void dn_nsp_send_disc(struct sock *sk, unsigned char type, - unsigned short reason, int gfp); + unsigned short reason, unsigned int __nocast gfp); extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type, unsigned short reason); extern void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval); @@ -29,14 +29,14 @@ extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags); extern void dn_nsp_output(struct sock *sk); extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum); -extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oob); +extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, unsigned int __nocast gfp, int oob); extern unsigned long dn_nsp_persist(struct sock *sk); extern int dn_nsp_xmit_timeout(struct sock *sk); extern int dn_nsp_rx(struct sk_buff *); extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb); -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri); +extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, unsigned int __nocast pri); extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err); #define NSP_REASON_OK 0 /* No error */ diff --git a/include/net/dn_route.h b/include/net/dn_route.h index d084721..11fe973 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -15,7 +15,7 @@ GNU General Public License for more details. *******************************************************************************/ -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri); +extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, unsigned int __nocast pri); extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags); extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 348f36b..34d4128 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -452,7 +452,8 @@ static struct proto dn_proto = { .obj_size = sizeof(struct dn_sock), }; -static struct sock *dn_alloc_sock(struct socket *sock, int gfp) +static struct sock *dn_alloc_sock(struct socket *sock, + unsigned int __nocast gfp) { struct dn_scp *scp; struct sock *sk = sk_alloc(PF_DECnet, gfp, &dn_proto, 1); @@ -804,7 +805,8 @@ static int dn_auto_bind(struct socket *sock) return rv; } -static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation) +static int dn_confirm_accept(struct sock *sk, long *timeo, + unsigned int __nocast allocation) { struct dn_scp *scp = DN_SK(sk); DEFINE_WAIT(wait); diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index 53633d3..cd08244 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -117,7 +117,8 @@ try_again: * The eventual aim is for each socket to have a cached header size * for its outgoing packets, and to set hdr from this when sk != NULL. */ -struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri) +struct sk_buff *dn_alloc_skb(struct sock *sk, int size, + unsigned int __nocast pri) { struct sk_buff *skb; int hdr = 64; @@ -210,7 +211,8 @@ static void dn_nsp_rtt(struct sock *sk, long rtt) * * Returns: The number of times the packet has been sent previously */ -static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, int gfp) +static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, + unsigned int __nocast gfp) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct sk_buff *skb2; @@ -350,7 +352,8 @@ static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *sk return ptr; } -void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth) +void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, + unsigned int __nocast gfp, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); @@ -517,7 +520,7 @@ static int dn_nsp_retrans_conn_conf(struct sock *sk) return 0; } -void dn_send_conn_conf(struct sock *sk, int gfp) +void dn_send_conn_conf(struct sock *sk, unsigned int __nocast gfp) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; @@ -549,7 +552,8 @@ void dn_send_conn_conf(struct sock *sk, int gfp) static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, - unsigned short reason, int gfp, struct dst_entry *dst, + unsigned short reason, unsigned int __nocast gfp, + struct dst_entry *dst, int ddl, unsigned char *dd, __u16 rem, __u16 loc) { struct sk_buff *skb = NULL; @@ -591,7 +595,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, - unsigned short reason, int gfp) + unsigned short reason, unsigned int __nocast gfp) { struct dn_scp *scp = DN_SK(sk); int ddl = 0; @@ -612,7 +616,7 @@ void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, { struct dn_skb_cb *cb = DN_SKB_CB(skb); int ddl = 0; - int gfp = GFP_ATOMIC; + unsigned int __nocast gfp = GFP_ATOMIC; dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl, NULL, cb->src_port, cb->dst_port); @@ -624,7 +628,7 @@ void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval) struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; unsigned char *ptr; - int gfp = GFP_ATOMIC; + unsigned int __nocast gfp = GFP_ATOMIC; if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL) return; @@ -659,7 +663,8 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) unsigned char menuver; struct dn_skb_cb *cb; unsigned char type = 1; - int allocation = (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC; + unsigned int __nocast allocation = + (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC; struct sk_buff *skb = dn_alloc_skb(sk, 200, allocation); if (!skb) -- cgit v0.10.2 From 8eea00a44d9f493869f8d30b72e3ed18475be556 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:42:15 -0700 Subject: [IPVS]: fix sparse gfp nocast warnings From: Randy Dunlap Fix implicit nocast warnings in ip_vs code: net/ipv4/ipvs/ip_vs_app.c:631:54: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 06b4235..ecb2b06 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -832,7 +832,7 @@ extern void ip_vs_app_inc_put(struct ip_vs_app *inc); extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff **pskb); extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff **pskb); -extern int ip_vs_skb_replace(struct sk_buff *skb, int pri, +extern int ip_vs_skb_replace(struct sk_buff *skb, unsigned int __nocast pri, char *o_buf, int o_len, char *n_buf, int n_len); extern int ip_vs_app_init(void); extern void ip_vs_app_cleanup(void); diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 6e092da..b942ff3 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -604,7 +604,7 @@ static struct file_operations ip_vs_app_fops = { /* * Replace a segment of data with a new segment */ -int ip_vs_skb_replace(struct sk_buff *skb, int pri, +int ip_vs_skb_replace(struct sk_buff *skb, unsigned int __nocast pri, char *o_buf, int o_len, char *n_buf, int n_len) { struct iphdr *iph; -- cgit v0.10.2 From c6f4fafccfa66f0530587ac3c11bb8fd0b8fe8ab Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:42:42 -0700 Subject: [NETFILTER]: fix sparse gfp nocast warnings Fix implicit nocast warnings in nfnetlink code: net/netfilter/nfnetlink.c:204:43: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 49a3900..34d6719 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -195,7 +195,8 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) { - int allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; + unsigned int __nocast allocation = + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; int err = 0; NETLINK_CB(skb).dst_group = group; -- cgit v0.10.2 From 00fa02334540ec795934737cd6e6ef8db2560731 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:43:04 -0700 Subject: [AF_KEY]: fix sparse gfp nocast warnings Fix implicit nocast warnings in net/key code: net/key/af_key.c:195:27: warning: implicit cast to nocast type net/key/af_key.c:1439:28: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/net/key/af_key.c b/net/key/af_key.c index 4879743..50d0a31 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -185,7 +185,7 @@ static int pfkey_release(struct socket *sock) } static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - int allocation, struct sock *sk) + unsigned int __nocast allocation, struct sock *sk) { int err = -ENOBUFS; @@ -217,7 +217,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, #define BROADCAST_ONE 1 #define BROADCAST_REGISTERED 2 #define BROADCAST_PROMISC_ONLY 4 -static int pfkey_broadcast(struct sk_buff *skb, int allocation, +static int pfkey_broadcast(struct sk_buff *skb, unsigned int __nocast allocation, int broadcast_flags, struct sock *one_sk) { struct sock *sk; @@ -1416,7 +1416,8 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, return 0; } -static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocation) +static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, + unsigned int __nocast allocation) { struct sk_buff *skb; struct sadb_msg *hdr; -- cgit v0.10.2 From dd13a285b79ba77416b96ee10f49097f4aaf48c5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:44:45 -0700 Subject: [RPC]: fix sparse gfp nocast warnings Fix nocast sparse warnings: net/rxrpc/call.c:2013:25: warning: implicit cast to nocast type net/rxrpc/connection.c:538:46: warning: implicit cast to nocast type net/sunrpc/sched.c:730:36: warning: implicit cast to nocast type net/sunrpc/sched.c:734:56: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/rxrpc/call.h b/include/rxrpc/call.h index f48f27e..8118731 100644 --- a/include/rxrpc/call.h +++ b/include/rxrpc/call.h @@ -203,7 +203,7 @@ extern int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, struct kvec *siov, uint8_t rxhdr_flags, - int alloc_flags, + unsigned int __nocast alloc_flags, int dup_data, size_t *size_sent); diff --git a/include/rxrpc/message.h b/include/rxrpc/message.h index 3a59df6..983d9f9 100644 --- a/include/rxrpc/message.h +++ b/include/rxrpc/message.h @@ -63,7 +63,7 @@ extern int rxrpc_conn_newmsg(struct rxrpc_connection *conn, uint8_t type, int count, struct kvec *diov, - int alloc_flags, + unsigned int __nocast alloc_flags, struct rxrpc_message **_msg); extern int rxrpc_conn_sendmsg(struct rxrpc_connection *conn, struct rxrpc_message *msg); diff --git a/net/rxrpc/call.c b/net/rxrpc/call.c index 5cfd4ca..86f7770 100644 --- a/net/rxrpc/call.c +++ b/net/rxrpc/call.c @@ -1923,7 +1923,7 @@ int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, struct kvec *siov, u8 rxhdr_flags, - int alloc_flags, + unsigned int __nocast alloc_flags, int dup_data, size_t *size_sent) { diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c index 61463c7..be4b2be 100644 --- a/net/rxrpc/connection.c +++ b/net/rxrpc/connection.c @@ -522,7 +522,7 @@ int rxrpc_conn_newmsg(struct rxrpc_connection *conn, uint8_t type, int dcount, struct kvec diov[], - int alloc_flags, + unsigned int __nocast alloc_flags, struct rxrpc_message **_msg) { struct rxrpc_message *msg; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f310403..ade730e 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -719,7 +719,7 @@ static void rpc_async_schedule(void *arg) void * rpc_malloc(struct rpc_task *task, size_t size) { - int gfp; + unsigned int __nocast gfp; if (task->tk_flags & RPC_TASK_SWAPPER) gfp = GFP_ATOMIC; -- cgit v0.10.2 From 3d2aef668920e8d93b77f145f8f647f62abe75db Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:45:14 -0700 Subject: [TEXTSEARCH]: fix sparse gfp nocast warnings Fix nocast sparse warnings: include/linux/textsearch.h:165:57: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h index 941f45a..1a4990e 100644 --- a/include/linux/textsearch.h +++ b/include/linux/textsearch.h @@ -158,7 +158,8 @@ extern unsigned int textsearch_find_continuous(struct ts_config *, #define TS_PRIV_ALIGNTO 8 #define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1)) -static inline struct ts_config *alloc_ts_config(size_t payload, int gfp_mask) +static inline struct ts_config *alloc_ts_config(size_t payload, + unsigned int __nocast gfp_mask) { struct ts_config *conf; diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 2cc79112..1b61fce 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -127,7 +127,7 @@ static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, } static struct ts_config *bm_init(const void *pattern, unsigned int len, - int gfp_mask) + unsigned int __nocast gfp_mask) { struct ts_config *conf; struct ts_bm *bm; diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c index d27c0a0..ef9779e 100644 --- a/lib/ts_fsm.c +++ b/lib/ts_fsm.c @@ -258,7 +258,7 @@ found_match: } static struct ts_config *fsm_init(const void *pattern, unsigned int len, - int gfp_mask) + unsigned int __nocast gfp_mask) { int i, err = -EINVAL; struct ts_config *conf; diff --git a/lib/ts_kmp.c b/lib/ts_kmp.c index 73266b9..e45f0f0 100644 --- a/lib/ts_kmp.c +++ b/lib/ts_kmp.c @@ -87,7 +87,7 @@ static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, } static struct ts_config *kmp_init(const void *pattern, unsigned int len, - int gfp_mask) + unsigned int __nocast gfp_mask) { struct ts_config *conf; struct ts_kmp *kmp; -- cgit v0.10.2 From 83fa3400ebcba307a60909824a251be984eb9567 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 4 Oct 2005 22:45:35 -0700 Subject: [XFRM]: fix sparse gfp nocast warnings Fix implicit nocast warnings in xfrm code: net/xfrm/xfrm_policy.c:232:47: warning: implicit cast to nocast type Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller diff --git a/include/net/xfrm.h b/include/net/xfrm.h index a9d0d8c..7564b2c 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -875,7 +875,7 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig } #endif -struct xfrm_policy *xfrm_policy_alloc(int gfp); +struct xfrm_policy *xfrm_policy_alloc(unsigned int __nocast gfp); extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index fda737d..c6a0d34 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -225,7 +225,7 @@ expired: * SPD calls. */ -struct xfrm_policy *xfrm_policy_alloc(int gfp) +struct xfrm_policy *xfrm_policy_alloc(unsigned int __nocast gfp) { struct xfrm_policy *policy; -- cgit v0.10.2 From 329d4dd72e5c3393a0c7aeebf3e62df77b196d71 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 5 Oct 2005 08:36:02 +0100 Subject: [PATCH] fix the breakage in sparc headers If we switch extern inline to static inline, we'd better switch the pre-declarations we use to say that these puppies have __attribute_const__ on them. Otherwise we get extern declaration followed by static inline one. Which makes gcc unhappy, and for a good reason... Signed-off-by: Al Viro Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds diff --git a/include/asm-sparc/btfixup.h b/include/asm-sparc/btfixup.h index 6b29503..c2868d0 100644 --- a/include/asm-sparc/btfixup.h +++ b/include/asm-sparc/btfixup.h @@ -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__; \ + static inline unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ static 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__; \ + static inline unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ static 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__; \ + static inline unsigned int ___af_##__name(void) __attribute_const__; \ extern unsigned ___as_##__name[2]; \ static 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__; \ + static inline unsigned int ___af_##__name(void) __attribute_const__; \ extern unsigned ___as_##__name[2]; \ static 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__; \ + static inline unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ static 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__; \ + static inline unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ static inline unsigned int ___hf_##__name(void) { \ unsigned int ret; \ diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index ae883f2..a14e986 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -194,19 +194,19 @@ BTFIXUPDEF_HALF(pte_writei) BTFIXUPDEF_HALF(pte_dirtyi) BTFIXUPDEF_HALF(pte_youngi) -extern int pte_write(pte_t pte) __attribute_const__; +static int pte_write(pte_t pte) __attribute_const__; static inline int pte_write(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_writei); } -extern int pte_dirty(pte_t pte) __attribute_const__; +static int pte_dirty(pte_t pte) __attribute_const__; static inline int pte_dirty(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi); } -extern int pte_young(pte_t pte) __attribute_const__; +static int pte_young(pte_t pte) __attribute_const__; static inline int pte_young(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_youngi); @@ -217,7 +217,7 @@ static inline int pte_young(pte_t pte) */ BTFIXUPDEF_HALF(pte_filei) -extern int pte_file(pte_t pte) __attribute_const__; +static int pte_file(pte_t pte) __attribute_const__; static inline int pte_file(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_filei); @@ -229,19 +229,19 @@ BTFIXUPDEF_HALF(pte_wrprotecti) BTFIXUPDEF_HALF(pte_mkcleani) BTFIXUPDEF_HALF(pte_mkoldi) -extern pte_t pte_wrprotect(pte_t pte) __attribute_const__; +static pte_t pte_wrprotect(pte_t pte) __attribute_const__; static 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__; +static pte_t pte_mkclean(pte_t pte) __attribute_const__; static 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__; +static pte_t pte_mkold(pte_t pte) __attribute_const__; static inline pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi)); @@ -278,7 +278,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__; +static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__; static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) | -- cgit v0.10.2 From 23cb8c297eb939b25e5a628dc9e8a71b17f1c44e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 5 Oct 2005 17:43:40 +1000 Subject: [PATCH] ppc: Fix timekeeping with HZ=250 on some Mac models Older Macs which uses the VIA chip timers to calibrate the timebase used some code that wouldn't work if HZ wasn't divisible by 100... This fixes it at least for 250. Not totally perfect but should be enough for now (so it at least works with the default value which is now 250). There is still a potential issue with the core using CLOCK_TICK_RATE to maintain xtime and CLOCK_TICK_RATE value on ppc32 is pure crap, but that is a different problem, this patch at least brings us back to our previous situation. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c index 778ce4f..efb819f 100644 --- a/arch/ppc/platforms/pmac_time.c +++ b/arch/ppc/platforms/pmac_time.c @@ -195,7 +195,7 @@ via_calibrate_decr(void) ; dend = get_dec(); - tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100)); + tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", -- cgit v0.10.2 From c0758146adbe39514e75ac860ce7e49f865c2297 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 3 Oct 2005 15:02:20 -0400 Subject: [PATCH] Fix drm 'debug' sysfs permissions Just enables some extra printk's, but still.. Only the sysadmin should be able to do that. Signed-off-by: Linus Torvalds diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 95a976c..70458cb 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c @@ -47,7 +47,7 @@ MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards"); MODULE_PARM_DESC(debug, "Enable debug output"); module_param_named(cards_limit, drm_cards_limit, int, 0444); -module_param_named(debug, drm_debug, int, 0666); +module_param_named(debug, drm_debug, int, 0600); drm_head_t **drm_heads; struct drm_sysfs_class *drm_class; -- cgit v0.10.2 From fab10fe37ad8dc4388fc444c89ef5aefe906354f Mon Sep 17 00:00:00 2001 From: Yan Zheng Date: Wed, 5 Oct 2005 12:08:13 -0700 Subject: [MCAST] ipv6: Fix address size in grec_size Signed-Off-By: Yan Zheng Acked-by: YOSHIFUJI Hideaki Acked-by: David L Stevens Signed-off-by: David S. Miller diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 519899f..39a96c7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1393,7 +1393,7 @@ static void mld_sendpack(struct sk_buff *skb) static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) { - return sizeof(struct mld2_grec) + 4*mld_scount(pmc,type,gdel,sdel); + return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel); } static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, -- cgit v0.10.2 From 42a39450f830c57432fd4e5644fa81f41ce7156d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 5 Oct 2005 12:09:31 -0700 Subject: [TCP]: BIC coding bug in Linux 2.6.13 Missing parenthesis in causes BIC to be slow in increasing congestion window. Spotted by Injong Rhee. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index b940346..6d80e06 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c @@ -136,7 +136,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) else if (cwnd < ca->last_max_cwnd + max_increment*(BICTCP_B-1)) /* slow start */ ca->cnt = (cwnd * (BICTCP_B-1)) - / cwnd-ca->last_max_cwnd; + / (cwnd - ca->last_max_cwnd); else /* linear increase */ ca->cnt = cwnd / max_increment; -- cgit v0.10.2 From 140e26fcd559f6988e5a9056385eecade19d9b49 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Wed, 5 Oct 2005 12:11:41 -0700 Subject: [IPV6]: Fix NS handing for proxy/anycast address Timer set up by pneigh_enqueue() ended up calling ndisc_rcv() via pndisc_redo(), which clears LOCALLY_ENQUEUED flag in NEIGH_CB(skb) and NS was queued again. Let's call ndisc_recv_ns() directly to avoid the loop. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 555a313..305d9ee 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1450,7 +1450,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, static void pndisc_redo(struct sk_buff *skb) { - ndisc_rcv(skb); + ndisc_recv_ns(skb); kfree_skb(skb); } -- cgit v0.10.2 From 77d8d7a6848c81084f413e1ec4982123a56e2ccb Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 5 Oct 2005 12:15:12 -0700 Subject: [IPSEC]: Document that policy direction is derived from the index. Here is a patch that adds a helper called xfrm_policy_id2dir to document the fact that the policy direction can be and is derived from the index. This is based on a patch by YOSHIFUJI Hideaki and 210313105@suda.edu.cn. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 7564b2c..b6e72f8 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -931,4 +931,9 @@ static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, } } +static inline int xfrm_policy_id2dir(u32 index) +{ + return index & 7; +} + #endif /* _NET_XFRM_H */ diff --git a/net/key/af_key.c b/net/key/af_key.c index 50d0a31..bbf0f69 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2154,6 +2154,7 @@ out: static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) { + unsigned int dir; int err; struct sadb_x_policy *pol; struct xfrm_policy *xp; @@ -2162,7 +2163,11 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) return -EINVAL; - xp = xfrm_policy_byid(0, pol->sadb_x_policy_id, + dir = xfrm_policy_id2dir(pol->sadb_x_policy_id); + if (dir >= XFRM_POLICY_MAX) + return -EINVAL; + + xp = xfrm_policy_byid(dir, pol->sadb_x_policy_id, hdr->sadb_msg_type == SADB_X_SPDDELETE2); if (xp == NULL) return -ENOENT; @@ -2174,9 +2179,9 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) { c.data.byid = 1; c.event = XFRM_MSG_DELPOLICY; - km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); + km_policy_notify(xp, dir, &c); } else { - err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1); + err = key_pol_get_resp(sk, xp, hdr, dir); } xfrm_pol_put(xp); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c6a0d34..061b44c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -163,7 +163,7 @@ static void xfrm_policy_timer(unsigned long data) if (xp->dead) goto out; - dir = xp->index & 7; + dir = xfrm_policy_id2dir(xp->index); if (xp->lft.hard_add_expires_seconds) { long tmo = xp->lft.hard_add_expires_seconds + @@ -417,7 +417,7 @@ struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); - for (p = &xfrm_policy_list[id & 7]; (pol=*p)!=NULL; p = &pol->next) { + for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { if (pol->index == id) { xfrm_pol_hold(pol); if (delete) -- cgit v0.10.2 From 3a867b36c3234673e61f883ebc11ad18f80a176f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 5 Oct 2005 12:16:04 -0700 Subject: [AX.25]: Fix packet socket crash Since changeset 98a82febb6340466824c3a453738d4fbd05db81a AX.25 is passing received IP and ARP packets to the stack through netif_rx() but we don't set the skb->mac.raw to right value which may result in a crash with applications that use a packet socket. Signed-off-by: Ralf Baechle DL5RB Signed-off-by: David S. Miller diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 810c9c7..73cfc34 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -123,7 +123,7 @@ int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb) } skb_pull(skb, 1); /* Remove PID */ - skb->h.raw = skb->data; + skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; skb->dev = ax25->ax25_dev->dev; skb->pkt_type = PACKET_HOST; diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 4e66eef..509afdd 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -58,7 +58,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) /* Spoof incoming device */ skb->dev = dev; - skb->h.raw = skb->data; + skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; skb->pkt_type = PACKET_HOST; -- cgit v0.10.2 From 782c3fd470abddf2525e34cf3131215a8f95e834 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Wed, 5 Oct 2005 12:21:36 -0700 Subject: [SPARC]: Remove some duplicated sparc32 config items Remove some duplicated items due to the inclusion of the general drivers/Kconfig file. These are now taken from drivers/char/Kconfig, and can be turned off there as well (which is desirable sometimes). Signed-off-by: Martin Habets Signed-off-by: David S. Miller diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index aba0539..6537445 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -25,62 +25,6 @@ source "init/Kconfig" menu "General machine setup" -config VT - bool - select INPUT - default y - ---help--- - If you say Y here, you will get support for terminal devices with - display and keyboard devices. These are called "virtual" because you - can run several virtual terminals (also called virtual consoles) on - one physical terminal. This is rather useful, for example one - virtual terminal can collect system messages and warnings, another - one can be used for a text-mode user session, and a third could run - an X session, all in parallel. Switching between virtual terminals - is done with certain key combinations, usually Alt-. - - The setterm command ("man setterm") can be used to change the - properties (such as colors or beeping) of a virtual terminal. The - man page console_codes(4) ("man console_codes") contains the special - character sequences that can be used to change those properties - directly. The fonts used on virtual terminals can be changed with - the setfont ("man setfont") command and the key bindings are defined - with the loadkeys ("man loadkeys") command. - - You need at least one virtual terminal device in order to make use - of your keyboard and monitor. Therefore, only people configuring an - embedded system would want to say N here in order to save some - memory; the only way to log into such a system is then via a serial - or network connection. - - If unsure, say Y, or else you won't be able to do much with your new - shiny Linux system :-) - -config VT_CONSOLE - bool - default y - ---help--- - The system console is the device which receives all kernel messages - and warnings and which allows logins in single user mode. If you - answer Y here, a virtual terminal (the device used to interact with - a physical terminal) can be used as system console. This is the most - common mode of operations, so you should say Y here unless you want - the kernel messages be output only to a serial port (in which case - you should say Y to "Console on serial port", below). - - If you do say Y here, by default the currently visible virtual - terminal (/dev/tty0) will be used as system console. You can change - that with a kernel command line option such as "console=tty3" which - would use the third virtual terminal as system console. (Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time.) - - If unsure, say Y. - -config HW_CONSOLE - bool - default y - config SMP bool "Symmetric multi-processing support (does not work on sun4/sun4c)" depends on BROKEN -- cgit v0.10.2 From e03eb5272b670e5002463c95fdc023410ba18484 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 5 Oct 2005 23:06:36 +0100 Subject: [ARM] 2954/1: Allow D and I cache and branch prediction disabling for ARMv6 Patch from Catalin Marinas There is no reason to not allow these config options. They are useful when the hardware has problems. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index db5e47d..c54e04c 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -370,21 +370,21 @@ config CPU_BIG_ENDIAN config CPU_ICACHE_DISABLE bool "Disable I-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 help Say Y here to disable the processor instruction cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_DISABLE bool "Disable D-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6 help Say Y here to disable the processor data cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" - depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DCACHE_DISABLE + depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_V6) && !CPU_DCACHE_DISABLE default y if CPU_ARM925T help Say Y here to use the data cache in writethrough mode. Unless you @@ -399,7 +399,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 + depends on CPU_ARM1020 || CPU_V6 help Say Y here to disable branch prediction. If unsure, say N. -- cgit v0.10.2 From 9ad98c5b4461e7dfa3754963200993a68825eab4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 5 Oct 2005 15:12:00 -0700 Subject: [SPARC64]: Fix initrd when net booting. By allocating early memory for the firmware page tables, we can write over the beginning of the initrd image. So what we do now is: 1) Read in firmware translations table while still on the firmware's trap table. 2) Switch to Linux trap table. 3) Init bootmem. 4) Build firmware page tables using __alloc_bootmem(). And this keeps the initrd from being clobbered. Signed-off-by: David S. Miller diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 4e2f71e..0d2e967 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -368,6 +368,7 @@ struct linux_prom_translation { unsigned long data; }; static struct linux_prom_translation prom_trans[512] __initdata; +static unsigned int prom_trans_ents __initdata; extern unsigned long prom_boot_page; extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); @@ -381,57 +382,7 @@ unsigned long kern_locked_tte_data; unsigned long prom_pmd_phys __read_mostly; unsigned int swapper_pgd_zero __read_mostly; -/* Allocate power-of-2 aligned chunks from the end of the - * kernel image. Return physical address. - */ -static inline unsigned long early_alloc_phys(unsigned long size) -{ - unsigned long base; - - BUILD_BUG_ON(size & (size - 1)); - - kern_size = (kern_size + (size - 1)) & ~(size - 1); - base = kern_base + kern_size; - kern_size += size; - - return base; -} - -static inline unsigned long load_phys32(unsigned long pa) -{ - unsigned long val; - - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=&r" (val) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); - - return val; -} - -static inline unsigned long load_phys64(unsigned long pa) -{ - unsigned long val; - - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=&r" (val) - : "r" (pa), "i" (ASI_PHYS_USE_EC)); - - return val; -} - -static inline void store_phys32(unsigned long pa, unsigned long val) -{ - __asm__ __volatile__("stwa %0, [%1] %2" - : /* no outputs */ - : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); -} - -static inline void store_phys64(unsigned long pa, unsigned long val) -{ - __asm__ __volatile__("stxa %0, [%1] %2" - : /* no outputs */ - : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC)); -} +static pmd_t *prompmd __read_mostly; #define BASE_PAGE_SIZE 8192 @@ -441,34 +392,28 @@ static inline void store_phys64(unsigned long pa, unsigned long val) */ unsigned long prom_virt_to_phys(unsigned long promva, int *error) { - unsigned long pmd_phys = (prom_pmd_phys + - ((promva >> 23) & 0x7ff) * sizeof(pmd_t)); - unsigned long pte_phys; - pmd_t pmd_ent; - pte_t pte_ent; + pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff); + pte_t *ptep; unsigned long base; - pmd_val(pmd_ent) = load_phys32(pmd_phys); - if (pmd_none(pmd_ent)) { + if (pmd_none(*pmdp)) { if (error) *error = 1; return 0; } - - pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; - pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t); - pte_val(pte_ent) = load_phys64(pte_phys); - if (!pte_present(pte_ent)) { + ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff); + if (!pte_present(*ptep)) { if (error) *error = 1; return 0; } if (error) { *error = 0; - return pte_val(pte_ent); + return pte_val(*ptep); } - base = pte_val(pte_ent) & _PAGE_PADDR; - return (base + (promva & (BASE_PAGE_SIZE - 1))); + base = pte_val(*ptep) & _PAGE_PADDR; + + return base + (promva & (BASE_PAGE_SIZE - 1)); } /* The obp translations are saved based on 8k pagesize, since obp can @@ -481,25 +426,20 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig unsigned long vaddr; for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { - unsigned long val, pte_phys, pmd_phys; - pmd_t pmd_ent; - int i; - - pmd_phys = (prom_pmd_phys + - (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t))); - pmd_val(pmd_ent) = load_phys32(pmd_phys); - if (pmd_none(pmd_ent)) { - pte_phys = early_alloc_phys(BASE_PAGE_SIZE); - - for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++) - store_phys64(pte_phys+i*sizeof(pte_t),0); + unsigned long val; + pmd_t *pmd; + pte_t *pte; - pmd_val(pmd_ent) = pte_phys >> 11UL; - store_phys32(pmd_phys, pmd_val(pmd_ent)); + pmd = prompmd + ((vaddr >> 23) & 0x7ff); + if (pmd_none(*pmd)) { + pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE, + PAGE_SIZE); + if (!pte) + prom_halt(); + memset(pte, 0, BASE_PAGE_SIZE); + pmd_set(pmd, pte); } - - pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL; - pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t)); + pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff); val = data; @@ -507,7 +447,8 @@ static void __init build_obp_range(unsigned long start, unsigned long end, unsig if (tlb_type == spitfire) val &= ~0x0003fe0000000000UL; - store_phys64(pte_phys, val | _PAGE_MODIFIED); + set_pte_at(&init_mm, vaddr, pte, + __pte(val | _PAGE_MODIFIED)); data += BASE_PAGE_SIZE; } @@ -520,13 +461,17 @@ static inline int in_obp_range(unsigned long vaddr) } #define OBP_PMD_SIZE 2048 -static void __init build_obp_pgtable(int prom_trans_ents) +static void __init build_obp_pgtable(void) { unsigned long i; - prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE); - for (i = 0; i < OBP_PMD_SIZE; i += 4) - store_phys32(prom_pmd_phys + i, 0); + prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE); + if (!prompmd) + prom_halt(); + + memset(prompmd, 0, OBP_PMD_SIZE); + + prom_pmd_phys = __pa(prompmd); for (i = 0; i < prom_trans_ents; i++) { unsigned long start, end; @@ -546,7 +491,7 @@ static void __init build_obp_pgtable(int prom_trans_ents) /* Read OBP translations property into 'prom_trans[]'. * Return the number of entries. */ -static int __init read_obp_translations(void) +static void __init read_obp_translations(void) { int n, node; @@ -567,8 +512,10 @@ static int __init read_obp_translations(void) prom_printf("prom_mappings: Couldn't get property.\n"); prom_halt(); } + n = n / sizeof(struct linux_prom_translation); - return n; + + prom_trans_ents = n; } static void __init remap_kernel(void) @@ -605,19 +552,21 @@ static void __init remap_kernel(void) } } -static void __init inherit_prom_mappings(void) -{ - int n; - n = read_obp_translations(); - build_obp_pgtable(n); +static void __init inherit_prom_mappings_pre(void) +{ + read_obp_translations(); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); remap_kernel(); prom_printf("done.\n"); +} +static void __init inherit_prom_mappings_post(void) +{ + build_obp_pgtable(); register_prom_callbacks(); } @@ -1570,8 +1519,7 @@ void __init paging_init(void) swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); - /* Inherit non-locked OBP mappings. */ - inherit_prom_mappings(); + inherit_prom_mappings_pre(); /* Ok, we can use our TLB miss and window trap handlers safely. * We need to do a quick peek here to see if we are on StarFire @@ -1582,15 +1530,23 @@ void __init paging_init(void) extern void setup_tba(int); setup_tba(this_is_starfire); } - - inherit_locked_prom_mappings(1); - __flush_tlb_all(); + /* Everything from this point forward, until we are done with + * inherit_prom_mappings_post(), must complete successfully + * without calling into the firmware. The firwmare page tables + * have not been built, but we are running on the Linux kernel's + * trap table. + */ + /* Setup bootmem... */ pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail); + inherit_prom_mappings_post(); + + inherit_locked_prom_mappings(1); + #ifdef CONFIG_DEBUG_PAGEALLOC kernel_physical_mapping_init(); #endif -- cgit v0.10.2 From a448a28589a6640736b8af1f2f57616c10bb37d5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 6 Oct 2005 13:09:42 +0100 Subject: [MFD] Fix gcc4 build errors in ucb1x00-core.c drivers/mfd/ucb1x00-core.c:555: error: static declaration of 'ucb1x00_class' follows non-static declaration drivers/mfd/ucb1x00.h:109: error: previous declaration of 'ucb1x00_class' was here Since ucb1x00_class isn't used by anything, remove the extern declaration and the symbol export. Signed-off-by: Russell King diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 10f6ce1..612564a 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -642,8 +642,6 @@ static void __exit ucb1x00_exit(void) module_init(ucb1x00_init); module_exit(ucb1x00_exit); -EXPORT_SYMBOL(ucb1x00_class); - EXPORT_SYMBOL(ucb1x00_io_set_dir); EXPORT_SYMBOL(ucb1x00_io_write); EXPORT_SYMBOL(ucb1x00_io_read); diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h index 6b63264..9c9a647 100644 --- a/drivers/mfd/ucb1x00.h +++ b/drivers/mfd/ucb1x00.h @@ -106,8 +106,6 @@ struct ucb1x00_irq { void (*fn)(int, void *); }; -extern struct class ucb1x00_class; - struct ucb1x00 { spinlock_t lock; struct mcp *mcp; -- cgit v0.10.2 From 76e677e25dd3d8af77d0b3810eacaacaf2f93f2f Mon Sep 17 00:00:00 2001 From: Bryan Sutula Date: Wed, 5 Oct 2005 11:02:06 -0600 Subject: [IA64] Avoid kernel hang during CMC interrupt storm I've noticed a kernel hang during a storm of CMC interrupts, which was tracked down to the continual execution of the interrupt handler. There's code in the CMC handler that's supposed to disable CMC interrupts and switch to polling mode when it sees a bunch of CMCs. Because disabling CMCs across all CPUs isn't safe in interrupt context, the disable is done with a schedule_work(). But with continual CMC interrupts, the schedule_work() never gets executed. The following patch immediately disables CMC interrupts for the current CPU. This then allows (at least) one CPU to ignore CMC interrupts, execute the schedule_work() code, and disable CMC interrupts on the rest of the CPUs. Acked-by: Keith Owens Signed-off-by: Bryan Sutula Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 6dc726a..d0a5106 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1016,6 +1016,11 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) cmc_polling_enabled = 1; spin_unlock(&cmc_history_lock); + /* If we're being hit with CMC interrupts, we won't + * ever execute the schedule_work() below. Need to + * disable CMC interrupts on this processor now. + */ + ia64_mca_cmc_vector_disable(NULL); schedule_work(&cmc_disable_work); /* -- cgit v0.10.2 From 2256c13b992b09f1f9563c26457aa048da2865df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 6 Oct 2005 20:43:54 -0700 Subject: [SPARC64]: Probe for power device on ISA bus too. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 946cee0..9e8362e 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -100,46 +101,83 @@ again: return 0; } -static int __init has_button_interrupt(struct linux_ebus_device *edev) +static int __init has_button_interrupt(unsigned int irq, int prom_node) { - if (edev->irqs[0] == PCI_IRQ_NONE) + if (irq == PCI_IRQ_NONE) return 0; - if (!prom_node_has_property(edev->prom_node, "button")) + if (!prom_node_has_property(prom_node, "button")) return 0; return 1; } -void __init power_init(void) +static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p) { struct linux_ebus *ebus; struct linux_ebus_device *edev; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "power")) { + *resp = &edev->resource[0]; + *irq_p = edev->irqs[0]; + *prom_node_p = edev->prom_node; + return 0; + } + } + } + return -ENODEV; +} + +static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p) +{ + struct sparc_isa_bridge *isa_bus; + struct sparc_isa_device *isa_dev; + + for_each_isa(isa_bus) { + for_each_isadev(isa_dev, isa_bus) { + if (!strcmp(isa_dev->prom_name, "power")) { + *resp = &isa_dev->resource; + *irq_p = isa_dev->irq; + *prom_node_p = isa_dev->prom_node; + return 0; + } + } + } + return -ENODEV; +} + +void __init power_init(void) +{ + struct resource *res = NULL; + unsigned int irq; + int prom_node; static int invoked; if (invoked) return; invoked = 1; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_name, "power")) - goto found; - } - } + if (!power_probe_ebus(&res, &irq, &prom_node)) + goto found; + + if (!power_probe_isa(&res, &irq, &prom_node)) + goto found; + return; found: - power_reg = ioremap(edev->resource[0].start, 0x4); + power_reg = ioremap(res->start, 0x4); printk("power: Control reg at %p ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(edev)) { + if (has_button_interrupt(irq, prom_node)) { if (kernel_thread(powerd, NULL, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; } printk("powerd running.\n"); - if (request_irq(edev->irqs[0], + if (request_irq(irq, power_handler, SA_SHIRQ, "power", NULL) < 0) printk("power: Error, cannot register IRQ handler.\n"); } else { -- cgit v0.10.2 From 5fe467ee9787007dd9b263eb42dde3742deb743b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Skytte=20J=F8rgensen?= Date: Thu, 6 Oct 2005 21:36:17 -0700 Subject: [SCTP] Fix sctp_get{pl}addrs() API to work with 32-bit apps on 64-bit kernels. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old socket options are marked with a _OLD suffix so that the existing 32-bit apps on 32-bit kernels do not break. Signed-off-by: Ivan Skytte Jørgensen Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index f6328ae..e81ab52 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -103,16 +103,20 @@ enum sctp_optname { #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_PEELOFF, /* peel off association. */ #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF - SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */ -#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM + SCTP_GET_PEER_ADDRS_NUM_OLD, /* Get number of peer addresss. */ +#define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD + SCTP_GET_PEER_ADDRS_OLD, /* Get all peer addresss. */ +#define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD + SCTP_GET_LOCAL_ADDRS_NUM_OLD, /* Get number of local addresss. */ +#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD + SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */ +#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD + SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ +#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS - SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */ -#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS - SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ -#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX }; /* @@ -559,11 +563,16 @@ struct sctp_status { * SCTP_GET_LOCAL_ADDRS socket options used internally to implement * sctp_getpaddrs() and sctp_getladdrs() API. */ -struct sctp_getaddrs { +struct sctp_getaddrs_old { sctp_assoc_t assoc_id; int addr_num; struct sockaddr __user *addrs; }; +struct sctp_getaddrs { + sctp_assoc_t assoc_id; /*input*/ + __u32 addr_num; /*output*/ + __u8 addrs[0]; /*output, variable size*/ +}; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* On user space Linux, these live in as an enum. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 91ec8c9..02e068d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3159,8 +3159,9 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval return 0; } -static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char __user *optval, int __user *optlen) +static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, return cnt; } -static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char __user *optval, int __user *optlen) +/* + * Old API for getting list of peer addresses. Does not work for 32-bit + * programs running on a 64-bit kernel + */ +static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; - struct sctp_getaddrs getaddrs; + struct sctp_getaddrs_old getaddrs; struct sctp_transport *from; void __user *to; union sctp_addr temp; struct sctp_sock *sp = sctp_sk(sk); int addrlen; - if (len != sizeof(struct sctp_getaddrs)) + if (len != sizeof(struct sctp_getaddrs_old)) return -EINVAL; - if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; @@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, if (cnt >= getaddrs.addr_num) break; } getaddrs.addr_num = cnt; - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) + return -EFAULT; + + return 0; +} + +static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, + char __user *optval, int __user *optlen) +{ + struct sctp_association *asoc; + struct list_head *pos; + int cnt = 0; + struct sctp_getaddrs getaddrs; + struct sctp_transport *from; + void __user *to; + union sctp_addr temp; + struct sctp_sock *sp = sctp_sk(sk); + int addrlen; + size_t space_left; + int bytes_copied; + + if (len < sizeof(struct sctp_getaddrs)) + return -EINVAL; + + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + return -EFAULT; + + /* For UDP-style sockets, id specifies the association to query. */ + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); + if (!asoc) + return -EINVAL; + + to = optval + offsetof(struct sctp_getaddrs,addrs); + space_left = len - sizeof(struct sctp_getaddrs) - + offsetof(struct sctp_getaddrs,addrs); + + list_for_each(pos, &asoc->peer.transport_addr_list) { + from = list_entry(pos, struct sctp_transport, transports); + memcpy(&temp, &from->ipaddr, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + if(space_left < addrlen) + return -ENOMEM; + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) + return -EFAULT; + to += addrlen; + cnt++; + space_left -= addrlen; + } + + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) + return -EFAULT; + bytes_copied = ((char __user *)to) - optval; + if (put_user(bytes_copied, optlen)) return -EFAULT; return 0; } -static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, - char __user *optval, - int __user *optlen) +static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, + char __user *optval, + int __user *optlen) { sctp_assoc_t id; struct sctp_bind_addr *bp; @@ -3306,8 +3366,8 @@ done: /* Helper function that copies local addresses to user and returns the number * of addresses copied. */ -static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, - void __user *to) +static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, + void __user *to) { struct list_head *pos; struct sctp_sockaddr_entry *addr; @@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, return cnt; } -static int sctp_getsockopt_local_addrs(struct sock *sk, int len, - char __user *optval, int __user *optlen) +static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, + void * __user *to, size_t space_left) +{ + struct list_head *pos; + struct sctp_sockaddr_entry *addr; + unsigned long flags; + union sctp_addr temp; + int cnt = 0; + int addrlen; + + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + list_for_each(pos, &sctp_local_addr_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + if ((PF_INET == sk->sk_family) && + (AF_INET6 == addr->a.sa.sa_family)) + continue; + memcpy(&temp, &addr->a, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), + &temp); + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if(space_leftaddress_list.next, struct sctp_sockaddr_entry, list); if (sctp_is_any(&addr->a)) { - cnt = sctp_copy_laddrs_to_user(sk, bp->port, - getaddrs.addr_num, to); + cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, + getaddrs.addr_num, + to); if (cnt < 0) { err = cnt; goto unlock; @@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, copy_getaddrs: getaddrs.addr_num = cnt; - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) err = -EFAULT; unlock: @@ -3427,6 +3528,99 @@ unlock: return err; } +static int sctp_getsockopt_local_addrs(struct sock *sk, int len, + char __user *optval, int __user *optlen) +{ + struct sctp_bind_addr *bp; + struct sctp_association *asoc; + struct list_head *pos; + int cnt = 0; + struct sctp_getaddrs getaddrs; + struct sctp_sockaddr_entry *addr; + void __user *to; + union sctp_addr temp; + struct sctp_sock *sp = sctp_sk(sk); + int addrlen; + rwlock_t *addr_lock; + int err = 0; + size_t space_left; + int bytes_copied; + + if (len <= sizeof(struct sctp_getaddrs)) + return -EINVAL; + + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) + return -EFAULT; + + /* + * For UDP-style sockets, id specifies the association to query. + * If the id field is set to the value '0' then the locally bound + * addresses are returned without regard to any particular + * association. + */ + if (0 == getaddrs.assoc_id) { + bp = &sctp_sk(sk)->ep->base.bind_addr; + addr_lock = &sctp_sk(sk)->ep->base.addr_lock; + } else { + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); + if (!asoc) + return -EINVAL; + bp = &asoc->base.bind_addr; + addr_lock = &asoc->base.addr_lock; + } + + to = optval + offsetof(struct sctp_getaddrs,addrs); + space_left = len - sizeof(struct sctp_getaddrs) - + offsetof(struct sctp_getaddrs,addrs); + + sctp_read_lock(addr_lock); + + /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid + * addresses from the global local address list. + */ + if (sctp_list_single_entry(&bp->address_list)) { + addr = list_entry(bp->address_list.next, + struct sctp_sockaddr_entry, list); + if (sctp_is_any(&addr->a)) { + cnt = sctp_copy_laddrs_to_user(sk, bp->port, + &to, space_left); + if (cnt < 0) { + err = cnt; + goto unlock; + } + goto copy_getaddrs; + } + } + + list_for_each(pos, &bp->address_list) { + addr = list_entry(pos, struct sctp_sockaddr_entry, list); + memcpy(&temp, &addr->a, sizeof(temp)); + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if(space_left < addrlen) + return -ENOMEM; /*fixme: right error?*/ + temp.v4.sin_port = htons(temp.v4.sin_port); + if (copy_to_user(to, &temp, addrlen)) { + err = -EFAULT; + goto unlock; + } + to += addrlen; + cnt ++; + space_left -= addrlen; + } + +copy_getaddrs: + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) + return -EFAULT; + bytes_copied = ((char __user *)to) - optval; + if (put_user(bytes_copied, optlen)) + return -EFAULT; + +unlock: + sctp_read_unlock(addr_lock); + return err; +} + /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as @@ -3807,12 +4001,20 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, case SCTP_INITMSG: retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); break; - case SCTP_GET_PEER_ADDRS_NUM: - retval = sctp_getsockopt_peer_addrs_num(sk, len, optval, + case SCTP_GET_PEER_ADDRS_NUM_OLD: + retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval, + optlen); + break; + case SCTP_GET_LOCAL_ADDRS_NUM_OLD: + retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval, + optlen); + break; + case SCTP_GET_PEER_ADDRS_OLD: + retval = sctp_getsockopt_peer_addrs_old(sk, len, optval, optlen); break; - case SCTP_GET_LOCAL_ADDRS_NUM: - retval = sctp_getsockopt_local_addrs_num(sk, len, optval, + case SCTP_GET_LOCAL_ADDRS_OLD: + retval = sctp_getsockopt_local_addrs_old(sk, len, optval, optlen); break; case SCTP_GET_PEER_ADDRS: -- cgit v0.10.2 From 20c9c825b12fcb8526a29cf20a17a5a3fc581726 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Thu, 6 Oct 2005 21:37:01 -0700 Subject: [SCTP] Fix SCTP socket options to work with 32-bit apps on 64-bit kernels. Adds alignment attribute to a few structures used with SCTP socket options so that the sizes and offsets remain the same when built using either 32 or 64 bit tools. Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index e81ab52..1c5f19f 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -243,7 +243,7 @@ struct sctp_paddr_change { int spc_state; int spc_error; sctp_assoc_t spc_assoc_id; -}; +} __attribute__((packed, aligned(4))); /* * spc_state: 32 bits (signed integer) @@ -468,7 +468,7 @@ struct sctp_assocparams { struct sctp_setpeerprim { sctp_assoc_t sspp_assoc_id; struct sockaddr_storage sspp_addr; -}; +} __attribute__((packed, aligned(4))); /* * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) @@ -481,7 +481,7 @@ struct sctp_setpeerprim { struct sctp_prim { sctp_assoc_t ssp_assoc_id; struct sockaddr_storage ssp_addr; -}; +} __attribute__((packed, aligned(4))); /* * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) @@ -508,7 +508,7 @@ struct sctp_paddrparams { struct sockaddr_storage spp_address; __u32 spp_hbinterval; __u16 spp_pathmaxrxt; -}; +} __attribute__((packed, aligned(4))); /* * 7.2.2 Peer Address Information @@ -527,7 +527,7 @@ struct sctp_paddrinfo { __u32 spinfo_srtt; __u32 spinfo_rto; __u32 spinfo_mtu; -}; +} __attribute__((packed, aligned(4))); /* Peer addresses's state. */ enum sctp_spinfo_state { -- cgit v0.10.2 From 829841146878e082613a49581ae252c071057c23 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Oct 2005 21:54:21 -0700 Subject: Avoid 'names_cache' memory leak with CONFIG_AUDITSYSCALL The nameidata "last.name" is always allocated with "__getname()", and should always be free'd with "__putname()". Using "putname()" without the underscores will leak memory, because the allocation will have been hidden from the AUDITSYSCALL code. Arguably the real bug is that the AUDITSYSCALL code is really broken, but in the meantime this fixes the problem people see. Reported by Robert Derr, patch by Rick Lindsley. Acked-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/namei.c b/fs/namei.c index 043d587..aa62dbd 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1551,19 +1551,19 @@ do_link: if (nd->last_type != LAST_NORM) goto exit; if (nd->last.name[nd->last.len]) { - putname(nd->last.name); + __putname(nd->last.name); goto exit; } error = -ELOOP; if (count++==32) { - putname(nd->last.name); + __putname(nd->last.name); goto exit; } dir = nd->dentry; down(&dir->d_inode->i_sem); path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); path.mnt = nd->mnt; - putname(nd->last.name); + __putname(nd->last.name); goto do_last; } -- cgit v0.10.2 From eb98129eec7fa605f0407dfd92d40ee8ddf5cd9a Mon Sep 17 00:00:00 2001 From: Tom 'spot' Callaway Date: Thu, 6 Oct 2005 22:14:59 -0700 Subject: [SPARC32]: Enable generic IOMAP. This helps some PCI stuff build. Signed-off-by: Tom 'spot' Callaway Signed-off-by: David S. Miller diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6537445..f7c51b8 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -21,6 +21,10 @@ config GENERIC_ISA_DMA bool default y +config GENERIC_IOMAP + bool + default y + source "init/Kconfig" menu "General machine setup" diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index a698562..8a3aef1e 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -5,6 +5,7 @@ CONFIG_MMU=y CONFIG_UID16=y CONFIG_HIGHMEM=y CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y # # Code maturity level options -- cgit v0.10.2 From 0f21ba7cc3320d33459ecb3f538f1a42040c29cd Mon Sep 17 00:00:00 2001 From: Eric Kinzie Date: Thu, 6 Oct 2005 22:19:28 -0700 Subject: [ATM]: add support for LECS addresses learned from network From: Eric Kinzie Signed-off-by: Chas Williams Signed-off-by: David S. Miller diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index f1fd849..aca9b34 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -76,6 +76,13 @@ struct atm_dev_stats { /* set interface ESI */ #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) /* force interface ESI */ +#define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc) + /* register a LECS address */ +#define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc) + /* unregister a LECS address */ +#define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc) + /* retrieve LECS address(es) */ + #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) /* get AAL layer statistics */ #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) @@ -328,6 +335,8 @@ struct atm_dev_addr { struct list_head entry; /* next address */ }; +enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS }; + struct atm_dev { const struct atmdev_ops *ops; /* device operations; NULL if unused */ const struct atmphy_ops *phy; /* PHY operations, may be undefined */ @@ -338,6 +347,7 @@ struct atm_dev { void *phy_data; /* private PHY date */ unsigned long flags; /* device flags (ATM_DF_*) */ struct list_head local; /* local ATM addresses */ + struct list_head lecs; /* LECS ATM addresses learned via ILMI */ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ struct atm_cirange ci_range; /* VPI/VCI range */ struct k_atm_dev_stats stats; /* statistics */ diff --git a/net/atm/addr.c b/net/atm/addr.c index a30d0bf..3060fd0 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev) sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); } -void atm_reset_addr(struct atm_dev *dev) +void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this, *p; + struct list_head *head; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry_safe(this, p, &dev->local, entry) { + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry_safe(this, p, head, entry) { list_del(&this->entry); kfree(this); } spin_unlock_irqrestore(&dev->lock, flags); - notify_sigd(dev); + if (head == &dev->local) + notify_sigd(dev); } -int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) +int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, + enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; + struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry(this, &dev->local, entry) { + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { spin_unlock_irqrestore(&dev->lock, flags); return -EEXIST; @@ -80,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) return -ENOMEM; } this->addr = *addr; - list_add(&this->entry, &dev->local); + list_add(&this->entry, head); spin_unlock_irqrestore(&dev->lock, flags); - notify_sigd(dev); + if (head == &dev->local) + notify_sigd(dev); return 0; } -int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) +int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, + enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; + struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry(this, &dev->local, entry) { + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { list_del(&this->entry); spin_unlock_irqrestore(&dev->lock, flags); kfree(this); - notify_sigd(dev); + if (head == &dev->local) + notify_sigd(dev); return 0; } } @@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) } int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, - size_t size) + size_t size, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; + struct list_head *head; int total = 0, error; struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; spin_lock_irqsave(&dev->lock, flags); - list_for_each_entry(this, &dev->local, entry) + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) total += sizeof(struct sockaddr_atmsvc); tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); if (!tmp_buf) { spin_unlock_irqrestore(&dev->lock, flags); return -ENOMEM; } - list_for_each_entry(this, &dev->local, entry) + list_for_each_entry(this, head, entry) memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); spin_unlock_irqrestore(&dev->lock, flags); error = total > size ? -E2BIG : total; diff --git a/net/atm/addr.h b/net/atm/addr.h index 3099d21..f39433a 100644 --- a/net/atm/addr.h +++ b/net/atm/addr.h @@ -9,10 +9,12 @@ #include #include - -void atm_reset_addr(struct atm_dev *dev); -int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); -int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); -int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); +void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); +int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, + enum atm_addr_type_t type); +int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, + enum atm_addr_type_t type); +int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, + size_t size, enum atm_addr_type_t type); #endif diff --git a/net/atm/resources.c b/net/atm/resources.c index a57a926..415d261 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type) dev->link_rate = ATM_OC3_PCR; spin_lock_init(&dev->lock); INIT_LIST_HEAD(&dev->local); + INIT_LIST_HEAD(&dev->lecs); return dev; } @@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EPERM; goto done; } - atm_reset_addr(dev); + atm_reset_addr(dev, ATM_ADDR_LOCAL); break; case ATM_ADDADDR: case ATM_DELADDR: + case ATM_ADDLECSADDR: + case ATM_DELLECSADDR: if (!capable(CAP_NET_ADMIN)) { error = -EPERM; goto done; @@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EFAULT; goto done; } - if (cmd == ATM_ADDADDR) - error = atm_add_addr(dev, &addr); + if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) + error = atm_add_addr(dev, &addr, + (cmd == ATM_ADDADDR ? + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); else - error = atm_del_addr(dev, &addr); + error = atm_del_addr(dev, &addr, + (cmd == ATM_DELADDR ? + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); goto done; } case ATM_GETADDR: - error = atm_get_addr(dev, buf, len); + case ATM_GETLECSADDR: + error = atm_get_addr(dev, buf, len, + (cmd == ATM_GETADDR ? + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); if (error < 0) goto done; size = error; -- cgit v0.10.2 From 06f619ccb3319759c2acf91c7ca02b6b1d9ed343 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Mon, 12 Sep 2005 11:47:04 +0200 Subject: [ALSA] snd_opl3sa2: add missing pnp_unregister_driver() calls OPL3SA2 driver Signed-off-by: Daniel Ritz Signed-off-by: Takashi Iwai diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index e2d2bab..4ba268f 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -914,6 +914,7 @@ static int __init alsa_card_opl3sa2_init(void) #endif #ifdef CONFIG_PNP pnp_unregister_card_driver(&opl3sa2_pnpc_driver); + pnp_unregister_driver(&opl3sa2_pnp_driver); #endif return -ENODEV; } @@ -927,6 +928,7 @@ static void __exit alsa_card_opl3sa2_exit(void) #ifdef CONFIG_PNP /* PnP cards first */ pnp_unregister_card_driver(&opl3sa2_pnpc_driver); + pnp_unregister_driver(&opl3sa2_pnp_driver); #endif for (idx = 0; idx < SNDRV_CARDS; idx++) snd_card_free(snd_opl3sa2_legacy[idx]); -- cgit v0.10.2 From 0444e2aca9ac89f571f0bb7781d12818719e4baf Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Tue, 13 Sep 2005 11:21:30 +0200 Subject: [ALSA] no templated index for mc97 controls AC97 Codec No index is templated for mdoem controls. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index e64cb07..f221eba 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1557,7 +1557,7 @@ static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97) /* build modem switches */ for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) return err; /* build chip specific controls */ -- cgit v0.10.2 From 27bcaa693c866b9bccf94ee5b60eaf705e90c341 Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Tue, 13 Sep 2005 11:23:13 +0200 Subject: [ALSA] no templated index for si3036 modem controls AC97 Codec No index is templated for si3036 modem controls. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 045ddc7..0238cc6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -2752,7 +2752,11 @@ AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1) static int patch_si3036_specific(ac97_t * ac97) { - return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036)); + int idx, err; + for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) + if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0) + return err; + return 0; } static struct snd_ac97_build_ops patch_si3036_ops = { -- cgit v0.10.2 From 84802f0df3425ae0f9987af0d35ea19910479ec0 Mon Sep 17 00:00:00 2001 From: Sasha Khapyorsky Date: Tue, 13 Sep 2005 11:25:54 +0200 Subject: [ALSA] hda-codec - 'empty' generic mfg-only codec HDA generic driver This creates 'empty' hda generic for unknown MFG-only codecs. Signed-off-by: Sasha Khapyorsky Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 5b829a1..d0eb9f2 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -881,10 +881,8 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec) struct hda_gspec *spec; int err; - if(!codec->afg) { - snd_printdd("hda_generic: no generic modem yet\n"); - return -ENODEV; - } + if(!codec->afg) + return 0; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) { -- cgit v0.10.2 From e8dede5a136bd7ef36d1779ea173cfd504dff0cb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 13 Sep 2005 11:28:53 +0200 Subject: [ALSA] hda-intel - Disable DMA position auto-correction HDA Intel driver Disable the auto-correction of DMA position temporarily. It doesn't work as expected yet... Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9590ece..6fe696e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1137,6 +1137,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) pos = azx_sd_readl(azx_dev, SD_LPIB); if (chip->position_fix == POS_FIX_FIFO) pos += azx_dev->fifo_size; +#if 0 /* disabled temprarily, auto-correction doesn't work well... */ else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) { /* check the validity of DMA position */ unsigned int diff = 0; @@ -1157,6 +1158,10 @@ static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) } azx_dev->period_updating = 0; } +#else + else if (chip->position_fix == POS_FIX_AUTO) + pos += azx_dev->fifo_size; +#endif } if (pos >= azx_dev->bufsize) pos = 0; -- cgit v0.10.2 From 1dcee12591320d79e4fc5bcdc4aa8a2522b7afdb Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Wed, 14 Sep 2005 20:52:25 +0200 Subject: [ALSA] Fix pm_message_t in PXA2XX-AC97 driver ARM PXA2XX driver Fix pm_message_t in PXA2XX-AC97 driver. Signed-off-by: Takashi Iwai diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 29450be..38b20ef 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -245,7 +245,7 @@ static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = { #ifdef CONFIG_PM -static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state) +static int pxa2xx_ac97_do_suspend(snd_card_t *card, pm_message_t state) { if (card->power_state != SNDRV_CTL_POWER_D3cold) { pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; -- cgit v0.10.2 From 460dc98afc6db255344a06c8da1196e2a2744758 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Fri, 16 Sep 2005 16:56:01 +0200 Subject: [ALSA] usb-audio: ignore Hercules DJ Console mixer errors USB generic driver Add a quirk entry for the Hercules DJ Console to ignore timeouts on some mixer control transfers. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index f05500b..13199ff 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -238,6 +238,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .selector_map = audigy2nx_selectors, }, { + /* Hercules DJ Console */ + .id = USB_ID(0x06f8, 0xd002), + .ignore_ctl_error = 1, + }, + { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, .ignore_ctl_error = 1, -- cgit v0.10.2 From 3a91e95969b84a56c7fef15ba25a5f6a17dd94b2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Sep 2005 18:46:36 +0200 Subject: [ALSA] remove bogus match method for ac97_bus AC97 Codec The bus_id is initialized with a generic identifier string which is not really useful for proper driver matching. Let the driver decide what it needs via its probe method instead. Signed-off-by: Nicolas Pitre Signed-off-by: Takashi Iwai diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c index 227f8b9..6f0e4bd 100644 --- a/sound/pci/ac97/ac97_bus.c +++ b/sound/pci/ac97/ac97_bus.c @@ -17,12 +17,13 @@ #include /* - * Codec families have names seperated by commas, so we search for an - * individual codec name within the family string. + * Let drivers decide whether they want to support given codec from their + * probe method. Drivers have direct access to the ac97_t structure and may + * decide based on the id field amongst other things. */ static int ac97_bus_match(struct device *dev, struct device_driver *drv) { - return (strstr(dev->bus_id, drv->name) != NULL); + return 1; } static int ac97_bus_suspend(struct device *dev, pm_message_t state) -- cgit v0.10.2 From 72e75de2df9a7116d0afbcd5810b2a8fd4bf7559 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Sep 2005 18:49:22 +0200 Subject: [ALSA] remove redundent assignment to the ac97 device structure AC97 Codec Don't use dev.platform_data to store a reference to the containing ac97_t structure. Such assignment is redundent since we can deduce the ac97_t structure location from the contained device structure. This sets platform_data free for other purposes. Signed-off-by: Nicolas Pitre Signed-off-by: Takashi Iwai diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index 2857cf0..d11f348 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -527,6 +527,8 @@ struct _snd_ac97 { struct device dev; }; +#define to_ac97_t(d) container_of(d, struct _snd_ac97, dev) + /* conditions */ static inline int ac97_is_audio(ac97_t * ac97) { diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index f221eba..41fc290 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1828,7 +1828,6 @@ static int snd_ac97_dev_register(snd_device_t *device) ac97->dev.bus = &ac97_bus_type; ac97->dev.parent = ac97->bus->card->dev; - ac97->dev.platform_data = ac97; ac97->dev.release = ac97_device_release; snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "card%d-%d", ac97->bus->card->number, ac97->num); if ((err = device_register(&ac97->dev)) < 0) { -- cgit v0.10.2 From 90b66e833261618e11d71a35f2488a7d664a4566 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Sep 2005 18:50:53 +0200 Subject: [ALSA] clean suspend/resume calls for ac97_bus_type AC97 Codec A single call to the driver suspend/resume method for each device is enough. The level and SUSPEND_*/RESUME_* arguments are deprecated and said to be removed eventually anyway (no other subsystem are using them anymore except platform devices). Signed-off-by: Nicolas Pitre Signed-off-by: Takashi Iwai diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c index 6f0e4bd..becbc42 100644 --- a/sound/pci/ac97/ac97_bus.c +++ b/sound/pci/ac97/ac97_bus.c @@ -30,13 +30,8 @@ static int ac97_bus_suspend(struct device *dev, pm_message_t state) { int ret = 0; - if (dev->driver && dev->driver->suspend) { - ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE); - if (ret == 0) - ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE); - if (ret == 0) - ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN); - } + if (dev->driver && dev->driver->suspend) + ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN); return ret; } @@ -44,13 +39,8 @@ static int ac97_bus_resume(struct device *dev) { int ret = 0; - if (dev->driver && dev->driver->resume) { + if (dev->driver && dev->driver->resume) ret = dev->driver->resume(dev, RESUME_POWER_ON); - if (ret == 0) - ret = dev->driver->resume(dev, RESUME_RESTORE_STATE); - if (ret == 0) - ret = dev->driver->resume(dev, RESUME_ENABLE); - } return ret; } -- cgit v0.10.2 From db99055f8d8eb54d9da55293a11b82e9d53ca80d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 16 Sep 2005 19:07:52 +0200 Subject: [ALSA] via82xx - Add a dxs whitelist entry VIA82xx driver Added a dxs whitelist entry for an ECS mobo. Signed-off-by: Takashi Iwai diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 6db7de6..964113f 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2147,6 +2147,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K }, { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */ { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */ + { .subvendor = 0x1019, .subdevice = 0xa101, .action = VIA_DXS_SRC }, { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */ { .subvendor = 0x1025, .subdevice = 0x0046, .action = VIA_DXS_SRC }, /* Acer Aspire 1524 WLMi */ { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ -- cgit v0.10.2 From 5a2a68f5a1dab785d60a4575f48af5b15ab6328d Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 19 Sep 2005 12:24:00 +0200 Subject: [ALSA] usb-audio: add Roland RD-700SX support USB generic driver Add a quirk entry for the Roland RD-700SX. This should work for the RD-300SX, too. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index f74e652..36f9a3b 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1010,6 +1010,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Roland", + /* RD-700SX, RD-300SX */ + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0003, + .in_cables = 0x0003 + } + } +}, /* Midiman/M-Audio devices */ { -- cgit v0.10.2 From 1e8bdcaf82268ac713cbbaffc14801147be42ae7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 19 Sep 2005 15:21:17 +0200 Subject: [ALSA] Add iBook 1.33GHz support PPC PMAC driver Added the support of iBook 1.33GHz. Signed-off-by: Takashi Iwai diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index e35b48d..392b2ab 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -988,6 +988,7 @@ static int __init snd_pmac_detect(pmac_t *chip) case 0x33: case 0x29: case 0x24: + case 0x50: case 0x5c: chip->num_freqs = ARRAY_SIZE(tumbler_freqs); chip->model = PMAC_SNAPPER; -- cgit v0.10.2 From f542fda8f8cd0cc0e4bffef42b27c7dc59cd07d3 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 20 Sep 2005 09:06:36 +0200 Subject: [ALSA] usb-audio: add more Yamaha USB MIDI devices USB generic driver Add quirk entries for four unknown Yamaha USB MIDI devices. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 36f9a3b..5c6b3da 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -117,6 +117,10 @@ YAMAHA_DEVICE(0x103a, NULL), YAMAHA_DEVICE(0x103b, NULL), YAMAHA_DEVICE(0x103c, NULL), YAMAHA_DEVICE(0x103d, NULL), +YAMAHA_DEVICE(0x103e, NULL), +YAMAHA_DEVICE(0x103f, NULL), +YAMAHA_DEVICE(0x1040, NULL), +YAMAHA_DEVICE(0x1041, NULL), YAMAHA_DEVICE(0x2000, "DGP-7"), YAMAHA_DEVICE(0x2001, "DGP-5"), YAMAHA_DEVICE(0x2002, NULL), -- cgit v0.10.2 From 31ab9523ed3773d5de7c07b3b6c4c00ddb06045e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Sep 2005 08:55:01 +0200 Subject: [ALSA] usb-audio: add another ID for the TerraTec PHASE26 USB generic driver There is another revision of the PHASE26 with a different product ID; add a quirk entry for that, too. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 5c6b3da..370f0e3 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1356,10 +1356,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* TerraTec devices */ +{ + USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "TerraTec", + .product_name = "PHASE 26", + .ifnum = 3, + .type = QUIRK_MIDI_STANDARD_INTERFACE + } +}, { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { - .vendor_name = "Terratec", + .vendor_name = "TerraTec", .product_name = "PHASE 26", .ifnum = 3, .type = QUIRK_MIDI_STANDARD_INTERFACE -- cgit v0.10.2 From d31cbbfd80a84696847913b7486a998481038663 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 26 Sep 2005 09:59:57 +0200 Subject: [ALSA] usb-audio: increase max buffer size USB generic driver Increase the maximum PCM buffer size to 1 MB. The USB driver doesn't have any inherent buffer size limit, and big multichannel interfaces may benefit from this. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index d5ae2055..2ead878 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -1444,9 +1444,9 @@ static snd_pcm_hardware_t snd_usb_playback = SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, - .buffer_bytes_max = (256*1024), + .buffer_bytes_max = 1024 * 1024, .period_bytes_min = 64, - .period_bytes_max = (128*1024), + .period_bytes_max = 512 * 1024, .periods_min = 2, .periods_max = 1024, }; @@ -1458,9 +1458,9 @@ static snd_pcm_hardware_t snd_usb_capture = SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, - .buffer_bytes_max = (256*1024), + .buffer_bytes_max = 1024 * 1024, .period_bytes_min = 64, - .period_bytes_max = (128*1024), + .period_bytes_max = 512 * 1024, .periods_min = 2, .periods_max = 1024, }; -- cgit v0.10.2 From a7175aab3f5cffe3c79575e56dfcfe87a41a74c7 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Sep 2005 13:13:38 +0200 Subject: [ALSA] fix HD audio ALC260 mono (un)mute HDA Codec driver The ALC260 'Mono Playback Switch' is marked as an output in patch_realtek.c. It actually does not work unless it is marked as an input. Go figure... This was tested and confirmed on an HP xw4300. Signed-off-by: John W. Linville Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 849b5b5..9aca9b4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2243,7 +2243,7 @@ static snd_kcontrol_new_t alc260_base_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), + ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), { @@ -2270,7 +2270,7 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), + ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), { -- cgit v0.10.2 From 1c1fa8b69e6d538bcc1e58791938b31a2354ee65 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Sep 2005 13:18:41 +0200 Subject: [ALSA] fix alc880_test_mixer typo HDA Codec driver Fix a typo (cut & paste) in the alc880_test_mixer structure. Signed-off-by: John W. Linville Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9aca9b4..f62597e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1385,8 +1385,8 @@ static snd_kcontrol_new_t alc880_test_mixer[] = { HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT), - ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT), + ALC_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), + ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), PIN_CTL_TEST("Front Pin Mode", 0x14), PIN_CTL_TEST("Surround Pin Mode", 0x15), PIN_CTL_TEST("CLFE Pin Mode", 0x16), -- cgit v0.10.2 From 92447f3f1a1c1af418eb1dfee85a7685d9b9a3ef Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 29 Sep 2005 13:20:45 +0200 Subject: [ALSA] fix HD audio ALC882 lfe (un)mute HDA Codec driver Mark the ALC882 'LFE Playback Switch' as an input, like the other playback switch settings. Signed-off-by: John W. Linville Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f62597e..429e478 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2501,7 +2501,7 @@ static snd_kcontrol_new_t alc882_base_mixer[] = { HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT), + ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), -- cgit v0.10.2 From 35451088f445955fe460a38b25b97c263ff35033 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 29 Sep 2005 13:25:14 +0200 Subject: [ALSA] Fix confliction of capture controls on ALC880 test model HDA Codec driver Fixed the confliction of capture controls on ALC880 'test' model. Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 429e478..7327deb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1409,18 +1409,6 @@ static snd_kcontrol_new_t alc880_test_mixer[] = { HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 2, - .info = alc_mux_enum_info, - .get = alc_mux_enum_get, - .put = alc_mux_enum_put, - }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Channel Mode", -- cgit v0.10.2 From c66186e1c966e7e115a86af55597c05c5512014b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 29 Sep 2005 13:49:44 +0200 Subject: [ALSA] via82xx - dxs_support entry for an ASUS mobo VIA82xx driver Addded a dxs_support entry for an ASUS mobo. Signed-off-by: Takashi Iwai diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 964113f..3c0205b 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2153,6 +2153,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ + { .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */ { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */ -- cgit v0.10.2 From f12aa40c9d76af5add413731d30565327219c41f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Sep 2005 16:56:59 +0200 Subject: [ALSA] emu10k1 - Fix loading of SBLive Game board EMU10K1/EMU10K2 driver Fixed the error at loading SBLive Game board (and possible other models). The PCI SSIDs of this board conflicts with SB Live 5.1 Platinum, which has no AC97 chip. Signed-off-by: Takashi Iwai diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 67bf3f1..14cb271 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1059,7 +1059,7 @@ typedef struct { unsigned char spk71; /* Has 7.1 speakers */ unsigned char sblive51; /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */ unsigned char spdif_bug; /* Has Spdif phasing bug */ - unsigned char ac97_chip; /* Has an AC97 chip */ + unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */ unsigned char ecard; /* APS EEPROM */ const char *driver; const char *name; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index e87e842..e9cd8e0 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -756,9 +756,12 @@ static emu_chip_details_t emu_chip_details[] = { .sblive51 = 1} , /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SBLive! Platinum 5.1 [SB0060]", + .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]", .id = "Live", .emu10k1_chip = 1, + .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum + * share the same IDs! + */ .sblive51 = 1} , {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index d71a72e..6994f90 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -802,8 +802,13 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu, .read = snd_emu10k1_ac97_read, }; - if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) - return err; + if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) { + if (emu->card_capabilities->ac97_chip == 1) + return err; + snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); + snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); + goto no_ac97; /* FIXME: get rid of ugly gotos.. */ + } pbus->no_vra = 1; /* we don't need VRA */ memset(&ac97, 0, sizeof(ac97)); @@ -836,6 +841,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu, for (; *c; c++) remove_ctl(card, *c); } else { + no_ac97: if (emu->card_capabilities->ecard) strcpy(emu->card->mixername, "EMU APS"); else if (emu->audigy) -- cgit v0.10.2 From 315e3bd717068624ce888f3d045a168acefc6ce8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 4 Oct 2005 08:42:10 +0200 Subject: [ALSA] korg1212: fix typo KORG1212 driver Add a missing comma that made the stateName array one entry too short. Signed-off-by: Clemens Ladisch diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 09f9cbe..5561fd4 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -442,7 +442,7 @@ static char* stateName[] = { "Setup for play", "Playing", "Monitor mode on", - "Calibrating" + "Calibrating", "Invalid" }; -- cgit v0.10.2 From b150869369adafb7cc0cf65ea500f9f3c4bbf857 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 4 Oct 2005 13:49:32 +0200 Subject: [ALSA] emu10k1 - Fix handling of ac97_chip=2 EMU10K1/EMU10K2 driver Fixed the handling of ac97_chip=2 capability type. The error occurs in snd_ac97_mixer(), not in snd_ac97_bus(). Also, release the unnecessary ac97_bus object in the error path. Signed-off-by: Takashi Iwai diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 6994f90..7cc831c 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -802,21 +802,22 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu, .read = snd_emu10k1_ac97_read, }; - if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) { - if (emu->card_capabilities->ac97_chip == 1) - return err; - snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); - snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); - goto no_ac97; /* FIXME: get rid of ugly gotos.. */ - } + if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) + return err; pbus->no_vra = 1; /* we don't need VRA */ memset(&ac97, 0, sizeof(ac97)); ac97.private_data = emu; ac97.private_free = snd_emu10k1_mixer_free_ac97; ac97.scaps = AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) - return err; + if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { + if (emu->card_capabilities->ac97_chip == 1) + return err; + snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); + snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); + snd_device_free(emu->card, pbus); + goto no_ac97; /* FIXME: get rid of ugly gotos.. */ + } if (emu->audigy) { /* set master volume to 0 dB */ snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000); -- cgit v0.10.2 From 4d060fd16946d767ee903804c6769a26d7da7ab2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 4 Oct 2005 13:50:44 +0200 Subject: [ALSA] ali5451 - Don't build non-existing modem PCM ALI5451 driver Don't build the modem PCM if the corresponding codec isn't detected. Signed-off-by: Takashi Iwai diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index d683f77..f35b558 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1993,8 +1993,10 @@ static int __devinit snd_ali_mixer(ali_t * codec) if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) { snd_printk("ali mixer %d creating error.\n", i); if(i == 0) - return err; - } + return err; + codec->num_of_codecs = 1; + break; + } } if (codec->spdif_support) { -- cgit v0.10.2 From 9c9565f709f28c12dadfe74b31f2c86ffd75f71e Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 5 Oct 2005 13:02:38 +0200 Subject: [ALSA] usb-audio: add another ID for Hercules DJ Console USB generic driver Add a mixer quirk entry for the Hercules DJ Console (Windows Edition) that uses a different USB product ID. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index 13199ff..c126443 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c @@ -238,7 +238,12 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .selector_map = audigy2nx_selectors, }, { - /* Hercules DJ Console */ + /* Hercules DJ Console (Windows Edition) */ + .id = USB_ID(0x06f8, 0xb000), + .ignore_ctl_error = 1, + }, + { + /* Hercules DJ Console (Macintosh Edition) */ .id = USB_ID(0x06f8, 0xd002), .ignore_ctl_error = 1, }, -- cgit v0.10.2 From a25f175c2f6962c38cdbacfc4b66b297f4fb54b2 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 5 Oct 2005 13:23:19 +0200 Subject: [ALSA] usb-audio: add MIDI quirk for Hercules DJ Console USB generic driver Add a quirk entry for the external MIDI ports of the Windows Edition of the Hercules DJ Console. Signed-off-by: Clemens Ladisch diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 370f0e3..948759d 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1028,6 +1028,27 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Guillemot devices */ +{ + /* + * This is for the "Windows Edition" where the external MIDI ports are + * the only MIDI ports; the control data is reported through HID + * interfaces. The "Macintosh Edition" has ID 0xd002 and uses standard + * compliant USB MIDI ports for external MIDI and controls. + */ + USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Hercules", + .product_name = "DJ Console (WE)", + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + } +}, + /* Midiman/M-Audio devices */ { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002), -- cgit v0.10.2 From d85c3553df5e24cb3117385f0a17e1cc0436d148 Mon Sep 17 00:00:00 2001 From: Tom 'spot' Callaway Date: Fri, 7 Oct 2005 13:05:56 -0700 Subject: [SPARC]: Fix p9100 framebuffer in 2.6 The attached patch fixes the p9100 framebuffer so that text is viewable (not black on black, like it was before the patch). The linux logo displays for a very short period of time, then is replaced by a grey box. This leads me to believe that this framebuffer would have problems in X, but since there hasn't been a weitek driver for X in several millennia, this isn't something that I can confirm or deny. But this patch does get color console working on my SPARCbook 3TX. Signed-off-by: Tom 'spot' Callaway Signed-off-by: David S. Miller diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 7808a01..b76a5a9 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -288,6 +288,9 @@ static void p9100_init_one(struct sbus_dev *sdev) all->par.physbase = sdev->reg_addrs[2].phys_addr; sbusfb_fill_var(&all->info.var, sdev->prom_node, 8); + all->info.var.red.length = 8; + all->info.var.green.length = 8; + all->info.var.blue.length = 8; linebytes = prom_getintdefault(sdev->prom_node, "linebytes", all->info.var.xres); @@ -323,6 +326,7 @@ static void p9100_init_one(struct sbus_dev *sdev) kfree(all); return; } + fb_set_cmap(&all->info.cmap, &all->info); list_add(&all->list, &p9100_list); -- cgit v0.10.2 From ba6399334dd8a75bd295de26496196c720abae0a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 7 Oct 2005 13:30:49 -0700 Subject: [SPARC64]: Fix userland FPU state corruption. We need to use stricter memory barriers around the block load and store instructions we use to save and restore the FPU register file. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index f685035dbd..11a8484 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -33,7 +33,7 @@ /* This is trivial with the new code... */ .globl do_fpdis do_fpdis: - sethi %hi(TSTATE_PEF), %g4 ! IEU0 + sethi %hi(TSTATE_PEF), %g4 rdpr %tstate, %g5 andcc %g5, %g4, %g0 be,pt %xcc, 1f @@ -50,18 +50,18 @@ do_fpdis: add %g0, %g0, %g0 ba,a,pt %xcc, rtrap_clr_l6 -1: ldub [%g6 + TI_FPSAVED], %g5 ! Load Group - wr %g0, FPRS_FEF, %fprs ! LSU Group+4bubbles - andcc %g5, FPRS_FEF, %g0 ! IEU1 Group - be,a,pt %icc, 1f ! CTI - clr %g7 ! IEU0 - ldx [%g6 + TI_GSR], %g7 ! Load Group -1: andcc %g5, FPRS_DL, %g0 ! IEU1 - bne,pn %icc, 2f ! CTI - fzero %f0 ! FPA - andcc %g5, FPRS_DU, %g0 ! IEU1 Group - bne,pn %icc, 1f ! CTI - fzero %f2 ! FPA +1: ldub [%g6 + TI_FPSAVED], %g5 + wr %g0, FPRS_FEF, %fprs + andcc %g5, FPRS_FEF, %g0 + be,a,pt %icc, 1f + clr %g7 + ldx [%g6 + TI_GSR], %g7 +1: andcc %g5, FPRS_DL, %g0 + bne,pn %icc, 2f + fzero %f0 + andcc %g5, FPRS_DU, %g0 + bne,pn %icc, 1f + fzero %f2 faddd %f0, %f2, %f4 fmuld %f0, %f2, %f6 faddd %f0, %f2, %f8 @@ -104,8 +104,10 @@ do_fpdis: add %g6, TI_FPREGS + 0xc0, %g2 faddd %f0, %f2, %f8 fmuld %f0, %f2, %f10 - ldda [%g1] ASI_BLK_S, %f32 ! grrr, where is ASI_BLK_NUCLEUS 8-( + membar #Sync + ldda [%g1] ASI_BLK_S, %f32 ldda [%g2] ASI_BLK_S, %f48 + membar #Sync faddd %f0, %f2, %f12 fmuld %f0, %f2, %f14 faddd %f0, %f2, %f16 @@ -116,7 +118,6 @@ do_fpdis: fmuld %f0, %f2, %f26 faddd %f0, %f2, %f28 fmuld %f0, %f2, %f30 - membar #Sync b,pt %xcc, fpdis_exit nop 2: andcc %g5, FPRS_DU, %g0 @@ -133,8 +134,10 @@ do_fpdis: add %g6, TI_FPREGS + 0x40, %g2 faddd %f32, %f34, %f36 fmuld %f32, %f34, %f38 - ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( + membar #Sync + ldda [%g1] ASI_BLK_S, %f0 ldda [%g2] ASI_BLK_S, %f16 + membar #Sync faddd %f32, %f34, %f40 fmuld %f32, %f34, %f42 faddd %f32, %f34, %f44 @@ -147,7 +150,6 @@ do_fpdis: fmuld %f32, %f34, %f58 faddd %f32, %f34, %f60 fmuld %f32, %f34, %f62 - membar #Sync ba,pt %xcc, fpdis_exit nop 3: mov SECONDARY_CONTEXT, %g3 @@ -158,7 +160,8 @@ do_fpdis: stxa %g2, [%g3] ASI_DMMU membar #Sync mov 0x40, %g2 - ldda [%g1] ASI_BLK_S, %f0 ! grrr, where is ASI_BLK_NUCLEUS 8-( + membar #Sync + ldda [%g1] ASI_BLK_S, %f0 ldda [%g1 + %g2] ASI_BLK_S, %f16 add %g1, 0x80, %g1 ldda [%g1] ASI_BLK_S, %f32 diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index ecfb42a..090dcca 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -312,32 +312,33 @@ kern_fpucheck: ldub [%g6 + TI_FPDEPTH], %l5 wr %g1, FPRS_FEF, %fprs ldx [%o1 + %o5], %g1 add %g6, TI_XFSR, %o1 - membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 add %g6, TI_FPREGS, %o3 brz,pn %l6, 1f add %g6, TI_FPREGS+0x40, %o4 + membar #Sync ldda [%o3 + %o2] ASI_BLK_P, %f0 ldda [%o4 + %o2] ASI_BLK_P, %f16 + membar #Sync 1: andcc %l2, FPRS_DU, %g0 be,pn %icc, 1f wr %g1, 0, %gsr add %o2, 0x80, %o2 + membar #Sync ldda [%o3 + %o2] ASI_BLK_P, %f32 ldda [%o4 + %o2] ASI_BLK_P, %f48 - 1: membar #Sync ldx [%o1 + %o5], %fsr 2: stb %l5, [%g6 + TI_FPDEPTH] ba,pt %xcc, rt_continue nop 5: wr %g0, FPRS_FEF, %fprs - membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 add %g6, TI_FPREGS+0x80, %o3 add %g6, TI_FPREGS+0xc0, %o4 + membar #Sync ldda [%o3 + %o2] ASI_BLK_P, %f32 ldda [%o4 + %o2] ASI_BLK_P, %f48 membar #Sync diff --git a/arch/sparc64/lib/VISsave.S b/arch/sparc64/lib/VISsave.S index 4e18989..a0ded5c 100644 --- a/arch/sparc64/lib/VISsave.S +++ b/arch/sparc64/lib/VISsave.S @@ -59,15 +59,17 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 be,pn %icc, 9b add %g6, TI_FPREGS, %g2 andcc %o5, FPRS_DL, %g0 - membar #StoreStore | #LoadStore be,pn %icc, 4f add %g6, TI_FPREGS+0x40, %g3 + membar #Sync stda %f0, [%g2 + %g1] ASI_BLK_P stda %f16, [%g3 + %g1] ASI_BLK_P + membar #Sync andcc %o5, FPRS_DU, %g0 be,pn %icc, 5f 4: add %g1, 128, %g1 + membar #Sync stda %f32, [%g2 + %g1] ASI_BLK_P stda %f48, [%g3 + %g1] ASI_BLK_P @@ -87,7 +89,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 sll %g1, 5, %g1 add %g6, TI_FPREGS+0xc0, %g3 wr %g0, FPRS_FEF, %fprs - membar #StoreStore | #LoadStore + membar #Sync stda %f32, [%g2 + %g1] ASI_BLK_P stda %f48, [%g3 + %g1] ASI_BLK_P membar #Sync @@ -128,8 +130,8 @@ VISenterhalf: be,pn %icc, 4f add %g6, TI_FPREGS, %g2 - membar #StoreStore | #LoadStore add %g6, TI_FPREGS+0x40, %g3 + membar #Sync stda %f0, [%g2 + %g1] ASI_BLK_P stda %f16, [%g3 + %g1] ASI_BLK_P membar #Sync -- cgit v0.10.2 From 4f55cd105c38af4aa157804729d694f864fbc78a Mon Sep 17 00:00:00 2001 From: Jean-Denis Boyer Date: Fri, 7 Oct 2005 13:44:35 -0700 Subject: [ATM]: [br2684] if we free the skb, we should return 0 From: "Jean-Denis Boyer" Signed-off-by: Chas Williams Signed-off-by: David S. Miller diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 289956c..72f3f7b 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -220,7 +220,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) /* netif_stop_queue(dev); */ dev_kfree_skb(skb); read_unlock(&devs_lock); - return -EUNATCH; + return 0; } if (!br2684_xmit_vcc(skb, brdev, brvcc)) { /* -- cgit v0.10.2 From 788e05a67c343fa22f2ae1d3ca264e7f15c25eaf Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 7 Oct 2005 17:46:19 +0400 Subject: [PATCH] fix do_coredump() vs SIGSTOP race Let's suppose we have 2 threads in thread group: A - does coredump B - has pending SIGSTOP thread A thread B do_coredump: get_signal_to_deliver: lock(->sighand) ->signal->flags = SIGNAL_GROUP_EXIT unlock(->sighand) lock(->sighand) signr = dequeue_signal() ->signal->flags |= SIGNAL_STOP_DEQUEUED return SIGSTOP; do_signal_stop: unlock(->sighand) coredump_wait: zap_threads: lock(tasklist_lock) send SIGKILL to B // signal_wake_up() does nothing unlock(tasklist_lock) lock(tasklist_lock) lock(->sighand) re-check sig->flags & SIGNAL_STOP_DEQUEUED, yes set_current_state(TASK_STOPPED); finish_stop: schedule(); // ->state == TASK_STOPPED wait_for_completion(&startup_done) // waits for complete() from B, // ->state == TASK_UNINTERRUPTIBLE We can't wake up 'B' in any way: SIGCONT will be ignored because handle_stop_signal() sees ->signal->flags & SIGNAL_GROUP_EXIT. sys_kill(SIGKILL)->__group_complete_signal() will choose uninterruptible 'A', so it can't help. sys_tkill(B, SIGKILL) will be ignored by specific_send_sig_info() because B already has pending SIGKILL. This scenario is not possbile if 'A' does do_group_exit(), because it sets sig->flags = SIGNAL_GROUP_EXIT and delivers SIGKILL to subthreads atomically, holding both tasklist_lock and sighand->lock. That means that do_signal_stop() will notice !SIGNAL_STOP_DEQUEUED after re-locking ->sighand. And it is not possible to any other thread to re-add SIGNAL_STOP_DEQUEUED later, because dequeue_signal() can only return SIGKILL. I think it is better to change do_coredump() to do sigaddset(SIGKILL) and signal_wake_up() under sighand->lock, but this patch is much simpler. Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds diff --git a/kernel/signal.c b/kernel/signal.c index 619b027..c135f5a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -578,7 +578,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) * is to alert stop-signal processing code when another * processor has come along and cleared the flag. */ - tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; + if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) + tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; } if ( signr && ((info->si_code & __SI_MASK) == __SI_TIMER) && -- cgit v0.10.2 From c2059b2e0b209a0674c21f78337bb158d3ccb22b Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 7 Oct 2005 14:43:22 +0100 Subject: [PATCH] yenta: fix build if YENTA && !CARDBUS (struct pcmcia_socket).tune_bridge only exists if CONFIG_CARDBUS is set but building yenta_socket without CardBus is valid. Signed-off-by: David Vrabel Signed-off-by: Linus Torvalds diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index da0b404..539b5cd 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -873,6 +873,7 @@ static int ti1250_override(struct yenta_socket *socket) * Some fixup code to make everybody happy (TM). */ +#ifdef CONFIG_CARDBUS /** * set/clear various test bits: * Defaults to clear the bit. @@ -927,7 +928,6 @@ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) config_writeb(socket, ENE_TEST_C9, test_c9); } - static int ene_override(struct yenta_socket *socket) { /* install tune_bridge() function */ @@ -935,6 +935,9 @@ static int ene_override(struct yenta_socket *socket) return ti1250_override(socket); } +#else +# define ene_override ti1250_override +#endif #endif /* _LINUX_TI113X_H */ -- cgit v0.10.2 From 74fd92c511bd4a0771ac0faaaef38bb1be3a29f6 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 7 Oct 2005 15:01:09 +0100 Subject: [PATCH] key: plug request_key_auth memleak Plug request_key_auth memleak. This can be triggered by unprivileged users, so is local DoS. Signed-off-by: Chris Wright Signed-Off-By: David Howells Signed-off-by: Linus Torvalds diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 1ecd3d3..f80a501 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -96,6 +96,7 @@ static void request_key_auth_destroy(struct key *key) kenter("{%d}", key->serial); key_put(rka->target_key); + kfree(rka); } /* end request_key_auth_destroy() */ -- cgit v0.10.2 From f1a9badcf6ecad9975240d94514721cb93932151 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 7 Oct 2005 15:04:52 +0100 Subject: [PATCH] Keys: Add request-key process documentation The attached patch adds documentation for the process by which request-key works, including how it permits helper processes to gain access to the requestor's keyrings. Signed-Off-By: David Howells Signed-off-by: Linus Torvalds diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt new file mode 100644 index 0000000..5f2b9c5 --- /dev/null +++ b/Documentation/keys-request-key.txt @@ -0,0 +1,161 @@ + =================== + KEY REQUEST SERVICE + =================== + +The key request service is part of the key retention service (refer to +Documentation/keys.txt). This document explains more fully how that the +requesting algorithm works. + +The process starts by either the kernel requesting a service by calling +request_key(): + + struct key *request_key(const struct key_type *type, + const char *description, + const char *callout_string); + +Or by userspace invoking the request_key system call: + + key_serial_t request_key(const char *type, + const char *description, + const char *callout_info, + key_serial_t dest_keyring); + +The main difference between the two access points is that the in-kernel +interface does not need to link the key to a keyring to prevent it from being +immediately destroyed. The kernel interface returns a pointer directly to the +key, and it's up to the caller to destroy the key. + +The userspace interface links the key to a keyring associated with the process +to prevent the key from going away, and returns the serial number of the key to +the caller. + + +=========== +THE PROCESS +=========== + +A request proceeds in the following manner: + + (1) Process A calls request_key() [the userspace syscall calls the kernel + interface]. + + (2) request_key() searches the process's subscribed keyrings to see if there's + a suitable key there. If there is, it returns the key. If there isn't, and + callout_info is not set, an error is returned. Otherwise the process + proceeds to the next step. + + (3) request_key() sees that A doesn't have the desired key yet, so it creates + two things: + + (a) An uninstantiated key U of requested type and description. + + (b) An authorisation key V that refers to key U and notes that process A + is the context in which key U should be instantiated and secured, and + from which associated key requests may be satisfied. + + (4) request_key() then forks and executes /sbin/request-key with a new session + keyring that contains a link to auth key V. + + (5) /sbin/request-key execs an appropriate program to perform the actual + instantiation. + + (6) The program may want to access another key from A's context (say a + Kerberos TGT key). It just requests the appropriate key, and the keyring + search notes that the session keyring has auth key V in its bottom level. + + This will permit it to then search the keyrings of process A with the + UID, GID, groups and security info of process A as if it was process A, + and come up with key W. + + (7) The program then does what it must to get the data with which to + instantiate key U, using key W as a reference (perhaps it contacts a + Kerberos server using the TGT) and then instantiates key U. + + (8) Upon instantiating key U, auth key V is automatically revoked so that it + may not be used again. + + (9) The program then exits 0 and request_key() deletes key V and returns key + U to the caller. + +This also extends further. If key W (step 5 above) didn't exist, key W would be +created uninstantiated, another auth key (X) would be created [as per step 3] +and another copy of /sbin/request-key spawned [as per step 4]; but the context +specified by auth key X will still be process A, as it was in auth key V. + +This is because process A's keyrings can't simply be attached to +/sbin/request-key at the appropriate places because (a) execve will discard two +of them, and (b) it requires the same UID/GID/Groups all the way through. + + +====================== +NEGATIVE INSTANTIATION +====================== + +Rather than instantiating a key, it is possible for the possessor of an +authorisation key to negatively instantiate a key that's under construction. +This is a short duration placeholder that causes any attempt at re-requesting +the key whilst it exists to fail with error ENOKEY. + +This is provided to prevent excessive repeated spawning of /sbin/request-key +processes for a key that will never be obtainable. + +Should the /sbin/request-key process exit anything other than 0 or die on a +signal, the key under construction will be automatically negatively +instantiated for a short amount of time. + + +==================== +THE SEARCH ALGORITHM +==================== + +A search of any particular keyring proceeds in the following fashion: + + (1) When the key management code searches for a key (keyring_search_aux) it + firstly calls key_permission(SEARCH) on the keyring it's starting with, + if this denies permission, it doesn't search further. + + (2) It considers all the non-keyring keys within that keyring and, if any key + matches the criteria specified, calls key_permission(SEARCH) on it to see + if the key is allowed to be found. If it is, that key is returned; if + not, the search continues, and the error code is retained if of higher + priority than the one currently set. + + (3) It then considers all the keyring-type keys in the keyring it's currently + searching. It calls key_permission(SEARCH) on each keyring, and if this + grants permission, it recurses, executing steps (2) and (3) on that + keyring. + +The process stops immediately a valid key is found with permission granted to +use it. Any error from a previous match attempt is discarded and the key is +returned. + +When search_process_keyrings() is invoked, it performs the following searches +until one succeeds: + + (1) If extant, the process's thread keyring is searched. + + (2) If extant, the process's process keyring is searched. + + (3) The process's session keyring is searched. + + (4) If the process has a request_key() authorisation key in its session + keyring then: + + (a) If extant, the calling process's thread keyring is searched. + + (b) If extant, the calling process's process keyring is searched. + + (c) The calling process's session keyring is searched. + +The moment one succeeds, all pending errors are discarded and the found key is +returned. + +Only if all these fail does the whole thing fail with the highest priority +error. Note that several errors may have come from LSM. + +The error priority is: + + EKEYREVOKED > EKEYEXPIRED > ENOKEY + +EACCES/EPERM are only returned on a direct search of a specific keyring where +the basal keyring does not grant Search permission. diff --git a/Documentation/keys.txt b/Documentation/keys.txt index b22e7c8..4afe03a 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -361,6 +361,8 @@ The main syscalls are: /sbin/request-key will be invoked in an attempt to obtain a key. The callout_info string will be passed as an argument to the program. + See also Documentation/keys-request-key.txt. + The keyctl syscall functions are: @@ -533,8 +535,8 @@ The keyctl syscall functions are: (*) Read the payload data from a key: - key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, - size_t buflen); + long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, + size_t buflen); This function attempts to read the payload data from the specified key into the buffer. The process must have read permission on the key to @@ -555,9 +557,9 @@ The keyctl syscall functions are: (*) Instantiate a partially constructed key. - key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key, - const void *payload, size_t plen, - key_serial_t keyring); + long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, + const void *payload, size_t plen, + key_serial_t keyring); If the kernel calls back to userspace to complete the instantiation of a key, userspace should use this call to supply data for the key before the @@ -576,8 +578,8 @@ The keyctl syscall functions are: (*) Negatively instantiate a partially constructed key. - key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key, - unsigned timeout, key_serial_t keyring); + long keyctl(KEYCTL_NEGATE, key_serial_t key, + unsigned timeout, key_serial_t keyring); If the kernel calls back to userspace to complete the instantiation of a key, userspace should use this call mark the key as negative before the @@ -688,6 +690,8 @@ payload contents" for more information. If successful, the key will have been attached to the default keyring for implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. + See also Documentation/keys-request-key.txt. + (*) When it is no longer required, the key should be released using: diff --git a/security/keys/request_key.c b/security/keys/request_key.c index e6dd366..5cc4bba 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -7,6 +7,8 @@ * 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. + * + * See Documentation/keys-request-key.txt */ #include diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index f80a501..a8e4069 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -7,6 +7,8 @@ * 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. + * + * See Documentation/keys-request-key.txt */ #include -- cgit v0.10.2 From 468ed2b0c85ec4310b429e60358213b6d077289e Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 7 Oct 2005 15:07:38 +0100 Subject: [PATCH] Keys: Split key permissions checking into a .c file The attached patch splits key permissions checking out of key-ui.h and moves it into a .c file. It's quite large and called quite a lot, and it's about to get bigger with the addition of LSM support for keys... key_any_permission() is also discarded as it's no longer used. Signed-Off-By: David Howells Signed-off-by: Linus Torvalds diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h index 918c34a..7a2e332 100644 --- a/include/linux/key-ui.h +++ b/include/linux/key-ui.h @@ -38,97 +38,16 @@ struct keyring_list { struct key *keys[0]; }; - /* * check to see whether permission is granted to use a key in the desired way */ -static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) -{ - struct key *key = key_ref_to_ptr(key_ref); - key_perm_t kperm; - - if (is_key_possessed(key_ref)) - kperm = key->perm >> 24; - else if (key->uid == current->fsuid) - kperm = key->perm >> 16; - else if (key->gid != -1 && - key->perm & KEY_GRP_ALL && - in_group_p(key->gid) - ) - kperm = key->perm >> 8; - else - kperm = key->perm; - - kperm = kperm & perm & KEY_ALL; - - return kperm == perm; -} - -/* - * check to see whether permission is granted to use a key in at least one of - * the desired ways - */ -static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm) -{ - struct key *key = key_ref_to_ptr(key_ref); - key_perm_t kperm; - - if (is_key_possessed(key_ref)) - kperm = key->perm >> 24; - else if (key->uid == current->fsuid) - kperm = key->perm >> 16; - else if (key->gid != -1 && - key->perm & KEY_GRP_ALL && - in_group_p(key->gid) - ) - kperm = key->perm >> 8; - else - kperm = key->perm; +extern int key_task_permission(const key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm); - kperm = kperm & perm & KEY_ALL; - - return kperm != 0; -} - -static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) -{ - int ret; - - task_lock(tsk); - ret = groups_search(tsk->group_info, gid); - task_unlock(tsk); - return ret; -} - -static inline int key_task_permission(const key_ref_t key_ref, - struct task_struct *context, - key_perm_t perm) +static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) { - struct key *key = key_ref_to_ptr(key_ref); - key_perm_t kperm; - - if (is_key_possessed(key_ref)) { - kperm = key->perm >> 24; - } - else if (key->uid == context->fsuid) { - kperm = key->perm >> 16; - } - else if (key->gid != -1 && - key->perm & KEY_GRP_ALL && ( - key->gid == context->fsgid || - key_task_groups_search(context, key->gid) - ) - ) { - kperm = key->perm >> 8; - } - else { - kperm = key->perm; - } - - kperm = kperm & perm & KEY_ALL; - - return kperm == perm; - + return key_task_permission(key_ref, current, perm); } extern key_ref_t lookup_user_key(struct task_struct *context, diff --git a/security/keys/Makefile b/security/keys/Makefile index c392d75..5145adf 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile @@ -6,6 +6,7 @@ obj-y := \ key.o \ keyring.o \ keyctl.o \ + permission.o \ process_keys.o \ request_key.o \ request_key_auth.o \ diff --git a/security/keys/permission.c b/security/keys/permission.c new file mode 100644 index 0000000..1c36516 --- /dev/null +++ b/security/keys/permission.c @@ -0,0 +1,70 @@ +/* permission.c: key permission determination + * + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * 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. + */ + +#include +#include "internal.h" + +/*****************************************************************************/ +/* + * check to see whether permission is granted to use a key in the desired way, + * but permit the security modules to override + */ +int key_task_permission(const key_ref_t key_ref, + struct task_struct *context, + key_perm_t perm) +{ + struct key *key; + key_perm_t kperm; + int ret; + + key = key_ref_to_ptr(key_ref); + + /* use the top 8-bits of permissions for keys the caller possesses */ + if (is_key_possessed(key_ref)) { + kperm = key->perm >> 24; + goto use_these_perms; + } + + /* use the second 8-bits of permissions for keys the caller owns */ + if (key->uid == context->fsuid) { + kperm = key->perm >> 16; + goto use_these_perms; + } + + /* use the third 8-bits of permissions for keys the caller has a group + * membership in common with */ + if (key->gid != -1 && key->perm & KEY_GRP_ALL) { + if (key->gid == context->fsgid) { + kperm = key->perm >> 8; + goto use_these_perms; + } + + task_lock(context); + ret = groups_search(context->group_info, key->gid); + task_unlock(context); + + if (ret) { + kperm = key->perm >> 8; + goto use_these_perms; + } + } + + /* otherwise use the least-significant 8-bits */ + kperm = key->perm; + +use_these_perms: + kperm = kperm & perm & KEY_ALL; + + return kperm == perm; + +} /* end key_task_permission() */ + +EXPORT_SYMBOL(key_task_permission); -- cgit v0.10.2 From 7ab501db8cb6659efdf04034e0de6b44c059a51b Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 7 Oct 2005 16:41:24 +0100 Subject: [PATCH] Keys: Possessor permissions should be additive This patch makes the possessor permissions on a key additive with user/group/other permissions on the same key. This permits extra rights to be granted to the possessor of a key without taking away any rights conferred by them owning the key or having common group membership. Signed-Off-By: David Howells Signed-off-by: Linus Torvalds diff --git a/security/keys/permission.c b/security/keys/permission.c index 1c36516..03db073 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -27,12 +27,6 @@ int key_task_permission(const key_ref_t key_ref, key = key_ref_to_ptr(key_ref); - /* use the top 8-bits of permissions for keys the caller possesses */ - if (is_key_possessed(key_ref)) { - kperm = key->perm >> 24; - goto use_these_perms; - } - /* use the second 8-bits of permissions for keys the caller owns */ if (key->uid == context->fsuid) { kperm = key->perm >> 16; @@ -61,6 +55,12 @@ int key_task_permission(const key_ref_t key_ref, kperm = key->perm; use_these_perms: + /* use the top 8-bits of permissions for keys the caller possesses + * - possessor permissions are additive with other permissions + */ + if (is_key_possessed(key_ref)) + kperm |= key->perm >> 24; + kperm = kperm & perm & KEY_ALL; return kperm == perm; -- cgit v0.10.2 From 3b0e77bd144203a507eb191f7117d2c5004ea1de Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 7 Oct 2005 19:41:34 +0200 Subject: [PATCH] scsi_ioctl: only warn for rejected commands We should not be warning about commands that we allow, even if they are unknown. So move the if-root-allow check up a notch. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 079ec34..382dea7 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -201,15 +201,15 @@ static int verify_command(struct file *file, unsigned char *cmd) return 0; } + /* And root can do any command.. */ + if (capable(CAP_SYS_RAWIO)) + return 0; + if (!type) { cmd_type[cmd[0]] = CMD_WARNED; printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]); } - /* And root can do any command.. */ - if (capable(CAP_SYS_RAWIO)) - return 0; - /* Otherwise fail it with an "Operation not permitted" */ return -EPERM; } -- cgit v0.10.2 From dd0fc66fb33cd610bc1a5db8a5e232d34879b4d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 7 Oct 2005 07:46:04 +0100 Subject: [PATCH] gfp flags annotations - part 1 - added typedef unsigned int __nocast gfp_t; - replaced __nocast uses for gfp flags with gfp_t - it gives exactly the same warnings as far as sparse is concerned, doesn't change generated code (from gcc point of view we replaced unsigned int with typedef) and documents what's going on far better. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c index 1032930..426b098 100644 --- a/arch/cris/arch-v32/drivers/pci/dma.c +++ b/arch/cris/arch-v32/drivers/pci/dma.c @@ -24,7 +24,7 @@ struct dma_coherent_mem { }; void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast gfp) + dma_addr_t *dma_handle, gfp_t gfp) { void *ret; struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c index 1e51427..25fe668 100644 --- a/arch/i386/kernel/pci-dma.c +++ b/arch/i386/kernel/pci-dma.c @@ -23,7 +23,7 @@ struct dma_coherent_mem { }; void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast gfp) + dma_addr_t *dma_handle, gfp_t gfp) { void *ret; struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c index 507eb9d..5f24600 100644 --- a/arch/ppc64/kernel/bpa_iommu.c +++ b/arch/ppc64/kernel/bpa_iommu.c @@ -310,7 +310,7 @@ static void bpa_map_iommu(void) static void *bpa_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { void *ret; diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c index 4da8e31..7c34196 100644 --- a/arch/ppc64/kernel/dma.c +++ b/arch/ppc64/kernel/dma.c @@ -53,7 +53,7 @@ int dma_set_mask(struct device *dev, u64 dma_mask) EXPORT_SYMBOL(dma_set_mask); void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { struct dma_mapping_ops *dma_ops = get_dma_ops(dev); diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c index 9032b6b..4d9b438 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/ppc64/kernel/iommu.c @@ -519,7 +519,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, * to the dma address (mapping) of the first page. */ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { void *ret = NULL; dma_addr_t mapping; diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/ppc64/kernel/pci_direct_iommu.c index b8f7f58..54055c8 100644 --- a/arch/ppc64/kernel/pci_direct_iommu.c +++ b/arch/ppc64/kernel/pci_direct_iommu.c @@ -31,7 +31,7 @@ #include "pci.h" static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { void *ret; diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c index 14647e0..d9e33b7 100644 --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/ppc64/kernel/pci_iommu.c @@ -76,7 +76,7 @@ static inline struct iommu_table *devnode_table(struct device *dev) * to the dma address (mapping) of the first page. */ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, flag); diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c index c90e1dd..0e555b7 100644 --- a/arch/ppc64/kernel/vio.c +++ b/arch/ppc64/kernel/vio.c @@ -218,7 +218,7 @@ static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist, } static void *vio_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag) + dma_addr_t *dma_handle, gfp_t flag) { return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, dma_handle, flag); diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index d74a7c5..4b6bf19c 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -795,7 +795,7 @@ static void drain_rx_pools (amb_dev * dev) { } static inline void fill_rx_pool (amb_dev * dev, unsigned char pool, - unsigned int __nocast priority) + gfp_t priority) { rx_in rx; amb_rxq * rxq; diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 5821974..7f7ec28 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1374,8 +1374,7 @@ static void reset_chip (struct fs_dev *dev) } } -static void __devinit *aligned_kmalloc (int size, unsigned int __nocast flags, - int alignment) +static void __devinit *aligned_kmalloc (int size, gfp_t flags, int alignment) { void *t; @@ -1466,7 +1465,7 @@ static inline int nr_buffers_in_freepool (struct fs_dev *dev, struct freepool *f working again after that... -- REW */ static void top_off_fp (struct fs_dev *dev, struct freepool *fp, - unsigned int __nocast gfp_flags) + gfp_t gfp_flags) { struct FS_BPENTRY *qe, *ne; struct sk_buff *skb; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 6f1a83c..14f6a62 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -178,7 +178,7 @@ fore200e_irq_itoa(int irq) static void* -fore200e_kmalloc(int size, unsigned int __nocast flags) +fore200e_kmalloc(int size, gfp_t flags) { void *chunk = kzalloc(size, flags); diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 60a7ef6..e2f64f9 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c @@ -156,7 +156,7 @@ dma_pool_create (const char *name, struct device *dev, static struct dma_page * -pool_alloc_page (struct dma_pool *pool, unsigned int __nocast mem_flags) +pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags) { struct dma_page *page; int mapsize; @@ -262,8 +262,7 @@ dma_pool_destroy (struct dma_pool *pool) * If such a memory block can't be allocated, null is returned. */ void * -dma_pool_alloc (struct dma_pool *pool, unsigned int __nocast mem_flags, - dma_addr_t *handle) +dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle) { unsigned long flags; struct dma_page *page; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 7e22a58..a280e67 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -229,7 +229,7 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) return 1; } -static void *pkt_rb_alloc(unsigned int __nocast gfp_mask, void *data) +static void *pkt_rb_alloc(gfp_t gfp_mask, void *data) { return kmalloc(sizeof(struct pkt_rb_node), gfp_mask); } @@ -2082,7 +2082,7 @@ static int pkt_close(struct inode *inode, struct file *file) } -static void *psd_pool_alloc(unsigned int __nocast gfp_mask, void *data) +static void *psd_pool_alloc(gfp_t gfp_mask, void *data) { return kmalloc(sizeof(struct packet_stacked_data), gfp_mask); } diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index a1bf8f0..4fa8523 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -308,7 +308,7 @@ unlock: } static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe, - size_t size, unsigned int __nocast flags, void *data) + size_t size, gfp_t flags, void *data) { struct urb *urb; struct usb_ctrlrequest *cr; diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 57c48bb..6756cb2 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -132,7 +132,7 @@ static struct usb_device_id blacklist_ids[] = { { } /* Terminating entry */ }; -static struct _urb *_urb_alloc(int isoc, unsigned int __nocast gfp) +static struct _urb *_urb_alloc(int isoc, gfp_t gfp) { struct _urb *_urb = kmalloc(sizeof(struct _urb) + sizeof(struct usb_iso_packet_descriptor) * isoc, gfp); diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 1422285..505677f 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -69,8 +69,7 @@ int cn_already_initialized = 0; * a new message. * */ -int cn_netlink_send(struct cn_msg *msg, u32 __group, - unsigned int __nocast gfp_mask) +int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask) { struct cn_callback_entry *__cbq; unsigned int size; diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 5fe4f2b..315f5ca 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -98,7 +98,7 @@ static struct hpsb_address_ops arm_ops = { static void queue_complete_cb(struct pending_request *req); -static struct pending_request *__alloc_pending_request(unsigned int __nocast flags) +static struct pending_request *__alloc_pending_request(gfp_t flags) { struct pending_request *req; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a4a4d9c..a14ca87 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -783,7 +783,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, u32 remote_qpn, u16 pkey_index, struct ib_ah *ah, int rmpp_active, int hdr_len, int data_len, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_buf *send_buf; diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 78de2dd..2626182 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -574,7 +574,7 @@ static void ib_sa_path_rec_release(struct ib_sa_query *sa_query) int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, struct ib_sa_path_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_path_rec *resp, void *context), @@ -676,7 +676,7 @@ static void ib_sa_service_rec_release(struct ib_sa_query *sa_query) int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_service_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_service_rec *resp, void *context), @@ -759,7 +759,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_mcmember_rec *resp, void *context), diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index b82bc31..b6148f6 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -96,7 +96,7 @@ static kmem_cache_t *_crypt_io_pool; /* * Mempool alloc and free functions for the page */ -static void *mempool_alloc_page(unsigned int __nocast gfp_mask, void *data) +static void *mempool_alloc_page(gfp_t gfp_mask, void *data) { return alloc_page(gfp_mask); } diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 9de0001..4809b20 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -32,7 +32,7 @@ struct io { static unsigned _num_ios; static mempool_t *_io_pool; -static void *alloc_io(unsigned int __nocast gfp_mask, void *pool_data) +static void *alloc_io(gfp_t gfp_mask, void *pool_data) { return kmalloc(sizeof(struct io), gfp_mask); } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 8632825..2375709 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -122,7 +122,7 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region) /* FIXME move this */ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); -static void *region_alloc(unsigned int __nocast gfp_mask, void *pool_data) +static void *region_alloc(gfp_t gfp_mask, void *pool_data) { return kmalloc(sizeof(struct region), gfp_mask); } diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 2863423..1151c3e 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -38,7 +38,7 @@ static mdk_personality_t multipath_personality; -static void *mp_pool_alloc(unsigned int __nocast gfp_flags, void *data) +static void *mp_pool_alloc(gfp_t gfp_flags, void *data) { struct multipath_bh *mpb; mpb = kmalloc(sizeof(*mpb), gfp_flags); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a93ca47..0e1f148 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -52,7 +52,7 @@ static mdk_personality_t raid1_personality; static void unplug_slaves(mddev_t *mddev); -static void * r1bio_pool_alloc(unsigned int __nocast gfp_flags, void *data) +static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data) { struct pool_info *pi = data; r1bio_t *r1_bio; @@ -79,7 +79,7 @@ static void r1bio_pool_free(void *r1_bio, void *data) #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) #define RESYNC_WINDOW (2048*1024) -static void * r1buf_pool_alloc(unsigned int __nocast gfp_flags, void *data) +static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) { struct pool_info *pi = data; struct page *page; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5bd1e9e..28dd028 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -47,7 +47,7 @@ static void unplug_slaves(mddev_t *mddev); -static void * r10bio_pool_alloc(unsigned int __nocast gfp_flags, void *data) +static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) { conf_t *conf = data; r10bio_t *r10_bio; @@ -81,7 +81,7 @@ static void r10bio_pool_free(void *r10_bio, void *data) * one for write (we recover only one drive per r10buf) * */ -static void * r10buf_pool_alloc(unsigned int __nocast gfp_flags, void *data) +static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) { conf_t *conf = data; struct page *page; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f0a5b77..f264ff1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1290,7 +1290,7 @@ static void bond_mc_list_destroy(struct bonding *bond) * Copy all the Multicast addresses from src to the bonding device dst */ static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, - unsigned int __nocast gfp_flag) + gfp_t gfp_flag) { struct dev_mc_list *dmi, *new_dmi; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 83334db..e4811b4 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -584,7 +584,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) return 0; } -static inline int rx_refill(struct net_device *ndev, unsigned int __nocast gfp) +static inline int rx_refill(struct net_device *ndev, gfp_t gfp) { struct ns83820 *dev = PRIV(ndev); unsigned i; diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h index 16edbb1..13006d7 100644 --- a/drivers/net/sungem.h +++ b/drivers/net/sungem.h @@ -1036,7 +1036,7 @@ struct gem { #define ALIGNED_RX_SKB_ADDR(addr) \ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) static __inline__ struct sk_buff *gem_alloc_skb(int size, - unsigned int __nocast gfp_flags) + gfp_t gfp_flags) { struct sk_buff *skb = alloc_skb(size + 64, gfp_flags); diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 0b5087f..cab0985 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -833,7 +833,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit) } static void * -zfcp_mempool_alloc(unsigned int __nocast gfp_mask, void *size) +zfcp_mempool_alloc(gfp_t gfp_mask, void *size) { return kmalloc((size_t) size, gfp_mask); } diff --git a/fs/bio.c b/fs/bio.c index 83a3495..7d81a93 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -75,7 +75,7 @@ struct bio_set { */ static struct bio_set *fs_bio_set; -static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) +static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) { struct bio_vec *bvl; struct biovec_slab *bp; @@ -155,7 +155,7 @@ inline void bio_init(struct bio *bio) * allocate bio and iovecs from the memory pools specified by the * bio_set structure. **/ -struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, struct bio_set *bs) +struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) { struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); @@ -181,7 +181,7 @@ out: return bio; } -struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs) +struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) { struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); @@ -277,7 +277,7 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) * * Like __bio_clone, only also allocates the returned bio */ -struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask) +struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) { struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set); @@ -1078,7 +1078,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) return bp; } -static void *bio_pair_alloc(unsigned int __nocast gfp_flags, void *data) +static void *bio_pair_alloc(gfp_t gfp_flags, void *data) { return kmalloc(sizeof(struct bio_pair), gfp_flags); } diff --git a/fs/buffer.c b/fs/buffer.c index 6cbfcea..1216c0d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3045,7 +3045,7 @@ static void recalc_bh_state(void) buffer_heads_over_limit = (tot > max_buffer_heads); } -struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags) +struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) { struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); if (ret) { diff --git a/fs/mpage.c b/fs/mpage.c index bb9aebe..c5adcdd 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -102,7 +102,7 @@ static struct bio *mpage_bio_submit(int rw, struct bio *bio) static struct bio * mpage_alloc(struct block_device *bdev, sector_t first_sector, int nr_vecs, - unsigned int __nocast gfp_flags) + gfp_t gfp_flags) { struct bio *bio; diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h index 006946e..590887b 100644 --- a/fs/ntfs/malloc.h +++ b/fs/ntfs/malloc.h @@ -40,7 +40,7 @@ * Depending on @gfp_mask the allocation may be guaranteed to succeed. */ static inline void *__ntfs_malloc(unsigned long size, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { if (likely(size <= PAGE_SIZE)) { BUG_ON(!size); diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 296480e..6c8dcf7 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -35,7 +35,7 @@ EXPORT_SYMBOL(posix_acl_permission); * Allocate a new ACL with the specified number of entries. */ struct posix_acl * -posix_acl_alloc(int count, unsigned int __nocast flags) +posix_acl_alloc(int count, gfp_t flags) { const size_t size = sizeof(struct posix_acl) + count * sizeof(struct posix_acl_entry); @@ -51,7 +51,7 @@ posix_acl_alloc(int count, unsigned int __nocast flags) * Clone an ACL. */ struct posix_acl * -posix_acl_clone(const struct posix_acl *acl, unsigned int __nocast flags) +posix_acl_clone(const struct posix_acl *acl, gfp_t flags) { struct posix_acl *clone = NULL; @@ -185,7 +185,7 @@ posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p) * Create an ACL representing the file mode permission bits of an inode. */ struct posix_acl * -posix_acl_from_mode(mode_t mode, unsigned int __nocast flags) +posix_acl_from_mode(mode_t mode, gfp_t flags) { struct posix_acl *acl = posix_acl_alloc(3, flags); if (!acl) diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 4b18455..d2653b5 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -45,7 +45,7 @@ void * -kmem_alloc(size_t size, unsigned int __nocast flags) +kmem_alloc(size_t size, gfp_t flags) { int retries = 0; unsigned int lflags = kmem_flags_convert(flags); @@ -67,7 +67,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) } void * -kmem_zalloc(size_t size, unsigned int __nocast flags) +kmem_zalloc(size_t size, gfp_t flags) { void *ptr; @@ -90,7 +90,7 @@ kmem_free(void *ptr, size_t size) void * kmem_realloc(void *ptr, size_t newsize, size_t oldsize, - unsigned int __nocast flags) + gfp_t flags) { void *new; @@ -105,7 +105,7 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize, } void * -kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) +kmem_zone_alloc(kmem_zone_t *zone, gfp_t flags) { int retries = 0; unsigned int lflags = kmem_flags_convert(flags); @@ -124,7 +124,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) } void * -kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags) +kmem_zone_zalloc(kmem_zone_t *zone, gfp_t flags) { void *ptr; diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 109fcf2..ee7010f 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -81,7 +81,7 @@ typedef unsigned long xfs_pflags_t; *(NSTATEP) = *(OSTATEP); \ } while (0) -static __inline unsigned int kmem_flags_convert(unsigned int __nocast flags) +static __inline unsigned int kmem_flags_convert(gfp_t flags) { unsigned int lflags = __GFP_NOWARN; /* we'll report problems, if need be */ @@ -125,13 +125,12 @@ kmem_zone_destroy(kmem_zone_t *zone) BUG(); } -extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); -extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); +extern void *kmem_zone_zalloc(kmem_zone_t *, gfp_t); +extern void *kmem_zone_alloc(kmem_zone_t *, gfp_t); -extern void *kmem_alloc(size_t, unsigned int __nocast); -extern void *kmem_realloc(void *, size_t, size_t, - unsigned int __nocast); -extern void *kmem_zalloc(size_t, unsigned int __nocast); +extern void *kmem_alloc(size_t, gfp_t); +extern void *kmem_realloc(void *, size_t, size_t, gfp_t); +extern void *kmem_zalloc(size_t, gfp_t); extern void kmem_free(void *, size_t); typedef struct shrinker *kmem_shaker_t; diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h index 8cef663..747d790 100644 --- a/include/asm-generic/dma-mapping.h +++ b/include/asm-generic/dma-mapping.h @@ -35,7 +35,7 @@ dma_set_mask(struct device *dev, u64 dma_mask) static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - unsigned int __nocast flag) + gfp_t flag) { BUG_ON(dev->bus != &pci_bus_type); @@ -168,7 +168,7 @@ dma_set_mask(struct device *dev, u64 dma_mask) static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - unsigned int __nocast flag) + gfp_t flag) { BUG(); return NULL; diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h index 563964b..e56c335 100644 --- a/include/asm-i386/dma-mapping.h +++ b/include/asm-i386/dma-mapping.h @@ -11,7 +11,7 @@ #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag); + dma_addr_t *dma_handle, gfp_t flag); void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h index 92b8ee7..061bfca 100644 --- a/include/asm-ppc/dma-mapping.h +++ b/include/asm-ppc/dma-mapping.h @@ -61,7 +61,7 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask) static inline void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t * dma_handle, - unsigned int __nocast gfp) + gfp_t gfp) { #ifdef CONFIG_NOT_COHERENT_CACHE return __dma_alloc_coherent(size, dma_handle, gfp); diff --git a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h index 9ad8ade..fb68fa2 100644 --- a/include/asm-ppc64/dma-mapping.h +++ b/include/asm-ppc64/dma-mapping.h @@ -19,7 +19,7 @@ extern int dma_supported(struct device *dev, u64 mask); extern int dma_set_mask(struct device *dev, u64 dma_mask); extern void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag); + dma_addr_t *dma_handle, gfp_t flag); extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle); extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, @@ -118,7 +118,7 @@ dma_cache_sync(void *vaddr, size_t size, */ struct dma_mapping_ops { void * (*alloc_coherent)(struct device *dev, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag); + dma_addr_t *dma_handle, gfp_t flag); void (*free_coherent)(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); dma_addr_t (*map_single)(struct device *dev, void *ptr, diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h index 72dcf81..c2f3b6e 100644 --- a/include/asm-ppc64/iommu.h +++ b/include/asm-ppc64/iommu.h @@ -122,7 +122,7 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, int nelems, enum dma_data_direction direction); extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, - dma_addr_t *dma_handle, unsigned int __nocast flag); + dma_addr_t *dma_handle, gfp_t flag); extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, void *vaddr, dma_addr_t dma_handle); extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index aca9b34..e7d0593 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -467,7 +467,7 @@ static inline void atm_dev_put(struct atm_dev *dev) int atm_charge(struct atm_vcc *vcc,int truesize); struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, - unsigned int __nocast gfp_flags); + gfp_t gfp_flags); int atm_pcr_goal(struct atm_trafprm *tp); void vcc_release_async(struct atm_vcc *vcc, int reply); diff --git a/include/linux/bio.h b/include/linux/bio.h index 6e1c79c..3344b4e8 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -276,8 +276,8 @@ extern void bio_pair_release(struct bio_pair *dbio); extern struct bio_set *bioset_create(int, int, int); extern void bioset_free(struct bio_set *); -extern struct bio *bio_alloc(unsigned int __nocast, int); -extern struct bio *bio_alloc_bioset(unsigned int __nocast, int, struct bio_set *); +extern struct bio *bio_alloc(gfp_t, int); +extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); extern void bio_put(struct bio *); extern void bio_free(struct bio *, struct bio_set *); @@ -287,7 +287,7 @@ extern int bio_phys_segments(struct request_queue *, struct bio *); extern int bio_hw_segments(struct request_queue *, struct bio *); extern void __bio_clone(struct bio *, struct bio *); -extern struct bio *bio_clone(struct bio *, unsigned int __nocast); +extern struct bio *bio_clone(struct bio *, gfp_t); extern void bio_init(struct bio *); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 9082849..6a1d154 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -172,7 +172,7 @@ void __brelse(struct buffer_head *); void __bforget(struct buffer_head *); void __breadahead(struct block_device *, sector_t block, int size); struct buffer_head *__bread(struct block_device *, sector_t block, int size); -struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags); +struct buffer_head *alloc_buffer_head(gfp_t gfp_flags); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); void FASTCALL(__lock_buffer(struct buffer_head *bh)); diff --git a/include/linux/connector.h b/include/linux/connector.h index 96582c9..95952cc 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -149,7 +149,7 @@ struct cn_dev { int cn_add_callback(struct cb_id *, char *, void (*callback) (void *)); void cn_del_callback(struct cb_id *); -int cn_netlink_send(struct cn_msg *, u32, unsigned int __nocast); +int cn_netlink_send(struct cn_msg *, u32, gfp_t); int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)); void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id); diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 24062a1..6e2deef 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -23,7 +23,7 @@ void cpuset_init_current_mems_allowed(void); void cpuset_update_current_mems_allowed(void); void cpuset_restrict_to_mems_allowed(unsigned long *nodes); int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl); -extern int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask); +extern int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask); extern int cpuset_excl_nodes_overlap(const struct task_struct *p); extern struct file_operations proc_cpuset_operations; extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer); @@ -49,8 +49,7 @@ static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl) return 1; } -static inline int cpuset_zone_allowed(struct zone *z, - unsigned int __nocast gfp_mask) +static inline int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) { return 1; } diff --git a/include/linux/dmapool.h b/include/linux/dmapool.h index 4932ee5..76f12f4 100644 --- a/include/linux/dmapool.h +++ b/include/linux/dmapool.h @@ -19,7 +19,7 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev, void dma_pool_destroy(struct dma_pool *pool); -void *dma_pool_alloc(struct dma_pool *pool, unsigned int __nocast mem_flags, +void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle); void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr); diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 4dc990f..3010e17 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -85,9 +85,9 @@ static inline void arch_free_page(struct page *page, int order) { } #endif extern struct page * -FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *)); +FASTCALL(__alloc_pages(gfp_t, unsigned int, struct zonelist *)); -static inline struct page *alloc_pages_node(int nid, unsigned int __nocast gfp_mask, +static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order) { if (unlikely(order >= MAX_ORDER)) @@ -98,17 +98,17 @@ static inline struct page *alloc_pages_node(int nid, unsigned int __nocast gfp_m } #ifdef CONFIG_NUMA -extern struct page *alloc_pages_current(unsigned int __nocast gfp_mask, unsigned order); +extern struct page *alloc_pages_current(gfp_t gfp_mask, unsigned order); static inline struct page * -alloc_pages(unsigned int __nocast gfp_mask, unsigned int order) +alloc_pages(gfp_t gfp_mask, unsigned int order) { if (unlikely(order >= MAX_ORDER)) return NULL; return alloc_pages_current(gfp_mask, order); } -extern struct page *alloc_page_vma(unsigned __nocast gfp_mask, +extern struct page *alloc_page_vma(gfp_t gfp_mask, struct vm_area_struct *vma, unsigned long addr); #else #define alloc_pages(gfp_mask, order) \ @@ -117,8 +117,8 @@ extern struct page *alloc_page_vma(unsigned __nocast gfp_mask, #endif #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) -extern unsigned long FASTCALL(__get_free_pages(unsigned int __nocast gfp_mask, unsigned int order)); -extern unsigned long FASTCALL(get_zeroed_page(unsigned int __nocast gfp_mask)); +extern unsigned long FASTCALL(__get_free_pages(gfp_t gfp_mask, unsigned int order)); +extern unsigned long FASTCALL(get_zeroed_page(gfp_t gfp_mask)); #define __get_free_page(gfp_mask) \ __get_free_pages((gfp_mask),0) diff --git a/include/linux/jbd.h b/include/linux/jbd.h index de09726..ff853b3 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -935,7 +935,7 @@ void journal_put_journal_head(struct journal_head *jh); */ extern kmem_cache_t *jbd_handle_cache; -static inline handle_t *jbd_alloc_handle(unsigned int __nocast gfp_flags) +static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags) { return kmem_cache_alloc(jbd_handle_cache, gfp_flags); } diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index c27cd42..48eccd8 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -35,8 +35,8 @@ struct kfifo { }; extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - unsigned int __nocast gfp_mask, spinlock_t *lock); -extern struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask, + gfp_t gfp_mask, spinlock_t *lock); +extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); extern void kfifo_free(struct kfifo *fifo); extern unsigned int __kfifo_put(struct kfifo *fifo, diff --git a/include/linux/mempool.h b/include/linux/mempool.h index 796220c..f2427d7 100644 --- a/include/linux/mempool.h +++ b/include/linux/mempool.h @@ -6,7 +6,7 @@ #include -typedef void * (mempool_alloc_t)(unsigned int __nocast gfp_mask, void *pool_data); +typedef void * (mempool_alloc_t)(gfp_t gfp_mask, void *pool_data); typedef void (mempool_free_t)(void *element, void *pool_data); typedef struct mempool_s { @@ -26,17 +26,16 @@ extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data, int nid); -extern int mempool_resize(mempool_t *pool, int new_min_nr, - unsigned int __nocast gfp_mask); +extern int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask); extern void mempool_destroy(mempool_t *pool); -extern void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask); +extern void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask); extern void mempool_free(void *element, mempool_t *pool); /* * A mempool_alloc_t and mempool_free_t that get the memory from * a slab that is passed in through pool_data. */ -void *mempool_alloc_slab(unsigned int __nocast gfp_mask, void *pool_data); +void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data); void mempool_free_slab(void *element, void *pool_data); #endif /* _LINUX_MEMPOOL_H */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index bdebdc5..ba25ca8 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -131,7 +131,7 @@ extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (* extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock); extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid, - __u32 group, unsigned int __nocast allocation); + __u32 group, gfp_t allocation); extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code); extern int netlink_register_notifier(struct notifier_block *nb); extern int netlink_unregister_notifier(struct notifier_block *nb); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index d9a2564..acbf31c 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -19,7 +19,7 @@ #define AS_EIO (__GFP_BITS_SHIFT + 0) /* IO error on async write */ #define AS_ENOSPC (__GFP_BITS_SHIFT + 1) /* ENOSPC on async write */ -static inline unsigned int __nocast mapping_gfp_mask(struct address_space * mapping) +static inline gfp_t mapping_gfp_mask(struct address_space * mapping) { return mapping->flags & __GFP_BITS_MASK; } diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 4caeddd..4bc2412 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -71,11 +71,11 @@ posix_acl_release(struct posix_acl *acl) /* posix_acl.c */ -extern struct posix_acl *posix_acl_alloc(int, unsigned int __nocast); -extern struct posix_acl *posix_acl_clone(const struct posix_acl *, unsigned int __nocast); +extern struct posix_acl *posix_acl_alloc(int, gfp_t); +extern struct posix_acl *posix_acl_clone(const struct posix_acl *, gfp_t); extern int posix_acl_valid(const struct posix_acl *); extern int posix_acl_permission(struct inode *, const struct posix_acl *, int); -extern struct posix_acl *posix_acl_from_mode(mode_t, unsigned int __nocast); +extern struct posix_acl *posix_acl_from_mode(mode_t, gfp_t); extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *); extern int posix_acl_create_masq(struct posix_acl *, mode_t *); extern int posix_acl_chmod_masq(struct posix_acl *, mode_t); diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 9c51917..045d476 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -50,7 +50,7 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items); -int radix_tree_preload(unsigned int __nocast gfp_mask); +int radix_tree_preload(gfp_t gfp_mask); void radix_tree_init(void); void *radix_tree_tag_set(struct radix_tree_root *root, unsigned long index, int tag); diff --git a/include/linux/security.h b/include/linux/security.h index 0e43460..627382e 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2634,8 +2634,7 @@ static inline int security_socket_getpeersec(struct socket *sock, char __user *o return security_ops->socket_getpeersec(sock, optval, optlen, len); } -static inline int security_sk_alloc(struct sock *sk, int family, - unsigned int __nocast priority) +static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { return security_ops->sk_alloc_security(sk, family, priority); } @@ -2752,8 +2751,7 @@ static inline int security_socket_getpeersec(struct socket *sock, char __user *o return -ENOPROTOOPT; } -static inline int security_sk_alloc(struct sock *sk, int family, - unsigned int __nocast priority) +static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { return 0; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 466c879..8f5d9e7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -302,37 +302,37 @@ struct sk_buff { extern void __kfree_skb(struct sk_buff *skb); extern struct sk_buff *__alloc_skb(unsigned int size, - unsigned int __nocast priority, int fclone); + gfp_t priority, int fclone); static inline struct sk_buff *alloc_skb(unsigned int size, - unsigned int __nocast priority) + gfp_t priority) { return __alloc_skb(size, priority, 0); } static inline struct sk_buff *alloc_skb_fclone(unsigned int size, - unsigned int __nocast priority) + gfp_t priority) { return __alloc_skb(size, priority, 1); } extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, unsigned int size, - unsigned int __nocast priority); + gfp_t priority); extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff *skb_clone(struct sk_buff *skb, - unsigned int __nocast priority); + gfp_t priority); extern struct sk_buff *skb_copy(const struct sk_buff *skb, - unsigned int __nocast priority); + gfp_t priority); extern struct sk_buff *pskb_copy(struct sk_buff *skb, - unsigned int __nocast gfp_mask); + gfp_t gfp_mask); extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, - unsigned int __nocast gfp_mask); + gfp_t gfp_mask); extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom); extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, int newtailroom, - unsigned int __nocast priority); + gfp_t priority); extern struct sk_buff * skb_pad(struct sk_buff *skb, int pad); #define dev_kfree_skb(a) kfree_skb(a) extern void skb_over_panic(struct sk_buff *skb, int len, @@ -484,7 +484,7 @@ static inline int skb_shared(const struct sk_buff *skb) * NULL is returned on a memory allocation failure. */ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, - unsigned int __nocast pri) + gfp_t pri) { might_sleep_if(pri & __GFP_WAIT); if (skb_shared(skb)) { @@ -516,7 +516,7 @@ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, * %NULL is returned on a memory allocation failure. */ static inline struct sk_buff *skb_unshare(struct sk_buff *skb, - unsigned int __nocast pri) + gfp_t pri) { might_sleep_if(pri & __GFP_WAIT); if (skb_cloned(skb)) { @@ -1017,7 +1017,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) * %NULL is returned in there is no free memory. */ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct sk_buff *skb = alloc_skb(length + 16, gfp_mask); if (likely(skb)) @@ -1130,8 +1130,8 @@ static inline int skb_can_coalesce(struct sk_buff *skb, int i, * If there is no free memory -ENOMEM is returned, otherwise zero * is returned and the old skb data released. */ -extern int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp); -static inline int skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp) +extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp); +static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) { return __skb_linearize(skb, gfp); } diff --git a/include/linux/slab.h b/include/linux/slab.h index 1f356f3..5fc04a1 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -61,11 +61,11 @@ extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned lo void (*)(void *, kmem_cache_t *, unsigned long)); extern int kmem_cache_destroy(kmem_cache_t *); extern int kmem_cache_shrink(kmem_cache_t *); -extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast); +extern void *kmem_cache_alloc(kmem_cache_t *, gfp_t); extern void kmem_cache_free(kmem_cache_t *, void *); extern unsigned int kmem_cache_size(kmem_cache_t *); extern const char *kmem_cache_name(kmem_cache_t *); -extern kmem_cache_t *kmem_find_general_cachep(size_t size, unsigned int __nocast gfpflags); +extern kmem_cache_t *kmem_find_general_cachep(size_t size, gfp_t gfpflags); /* Size description struct for general caches. */ struct cache_sizes { @@ -74,9 +74,9 @@ struct cache_sizes { kmem_cache_t *cs_dmacachep; }; extern struct cache_sizes malloc_sizes[]; -extern void *__kmalloc(size_t, unsigned int __nocast); +extern void *__kmalloc(size_t, gfp_t); -static inline void *kmalloc(size_t size, unsigned int __nocast flags) +static inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { int i = 0; @@ -99,7 +99,7 @@ found: return __kmalloc(size, flags); } -extern void *kzalloc(size_t, unsigned int __nocast); +extern void *kzalloc(size_t, gfp_t); /** * kcalloc - allocate memory for an array. The memory is set to zero. @@ -107,7 +107,7 @@ extern void *kzalloc(size_t, unsigned int __nocast); * @size: element size. * @flags: the type of memory to allocate. */ -static inline void *kcalloc(size_t n, size_t size, unsigned int __nocast flags) +static inline void *kcalloc(size_t n, size_t size, gfp_t flags) { if (n != 0 && size > INT_MAX / n) return NULL; @@ -118,15 +118,14 @@ extern void kfree(const void *); extern unsigned int ksize(const void *); #ifdef CONFIG_NUMA -extern void *kmem_cache_alloc_node(kmem_cache_t *, - unsigned int __nocast flags, int node); -extern void *kmalloc_node(size_t size, unsigned int __nocast flags, int node); +extern void *kmem_cache_alloc_node(kmem_cache_t *, gfp_t flags, int node); +extern void *kmalloc_node(size_t size, gfp_t flags, int node); #else static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node) { return kmem_cache_alloc(cachep, flags); } -static inline void *kmalloc_node(size_t size, unsigned int __nocast flags, int node) +static inline void *kmalloc_node(size_t size, gfp_t flags, int node) { return kmalloc(size, flags); } diff --git a/include/linux/string.h b/include/linux/string.h index dab2652ac..369be32 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -88,7 +88,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t); extern void * memchr(const void *,int,__kernel_size_t); #endif -extern char *kstrdup(const char *s, unsigned int __nocast gfp); +extern char *kstrdup(const char *s, gfp_t gfp); #ifdef __cplusplus } diff --git a/include/linux/swap.h b/include/linux/swap.h index 3c9ff00..a7bf1a3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -147,7 +147,7 @@ struct swap_list_t { #define vm_swap_full() (nr_swap_pages*2 < total_swap_pages) /* linux/mm/oom_kill.c */ -extern void out_of_memory(unsigned int __nocast gfp_mask, int order); +extern void out_of_memory(gfp_t gfp_mask, int order); /* linux/mm/memory.c */ extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *); diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h index 1a4990e..515046d 100644 --- a/include/linux/textsearch.h +++ b/include/linux/textsearch.h @@ -159,7 +159,7 @@ extern unsigned int textsearch_find_continuous(struct ts_config *, #define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1)) static inline struct ts_config *alloc_ts_config(size_t payload, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct ts_config *conf; diff --git a/include/linux/types.h b/include/linux/types.h index 2b678c2..0aee34f 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -165,6 +165,10 @@ typedef __u64 __bitwise __le64; typedef __u64 __bitwise __be64; #endif +#ifdef __KERNEL__ +typedef unsigned __nocast gfp_t; +#endif + struct ustat { __kernel_daddr_t f_tfree; __kernel_ino_t f_tinode; diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index b244f69..3701a06 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -34,8 +34,8 @@ struct vm_struct { extern void *vmalloc(unsigned long size); extern void *vmalloc_exec(unsigned long size); extern void *vmalloc_32(unsigned long size); -extern void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask, pgprot_t prot); -extern void *__vmalloc_area(struct vm_struct *area, unsigned int __nocast gfp_mask, pgprot_t prot); +extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); +extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot); extern void vfree(void *addr); extern void *vmap(struct page **pages, unsigned int count, diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 6dfa4a6..2104586 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -136,7 +136,7 @@ struct bt_skb_cb { }; #define bt_cb(skb) ((struct bt_skb_cb *)(skb->cb)) -static inline struct sk_buff *bt_skb_alloc(unsigned int len, unsigned int __nocast how) +static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) { struct sk_buff *skb; diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index ffea9d5..fbe557f 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -230,7 +230,7 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, u8 xon_char, u8 xoff_char, u16 param_mask); /* ---- RFCOMM DLCs (channels) ---- */ -struct rfcomm_dlc *rfcomm_dlc_alloc(unsigned int __nocast prio); +struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio); void rfcomm_dlc_free(struct rfcomm_dlc *d); int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel); int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason); diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h index 8a0891e..1ba03be 100644 --- a/include/net/dn_nsp.h +++ b/include/net/dn_nsp.h @@ -19,9 +19,9 @@ extern void dn_nsp_send_data_ack(struct sock *sk); extern void dn_nsp_send_oth_ack(struct sock *sk); extern void dn_nsp_delayed_ack(struct sock *sk); extern void dn_send_conn_ack(struct sock *sk); -extern void dn_send_conn_conf(struct sock *sk, unsigned int __nocast gfp); +extern void dn_send_conn_conf(struct sock *sk, gfp_t gfp); extern void dn_nsp_send_disc(struct sock *sk, unsigned char type, - unsigned short reason, unsigned int __nocast gfp); + unsigned short reason, gfp_t gfp); extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type, unsigned short reason); extern void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval); @@ -29,14 +29,14 @@ extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags); extern void dn_nsp_output(struct sock *sk); extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum); -extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, unsigned int __nocast gfp, int oob); +extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, int oob); extern unsigned long dn_nsp_persist(struct sock *sk); extern int dn_nsp_xmit_timeout(struct sock *sk); extern int dn_nsp_rx(struct sk_buff *); extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb); -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, unsigned int __nocast pri); +extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err); #define NSP_REASON_OK 0 /* No error */ diff --git a/include/net/dn_route.h b/include/net/dn_route.h index 11fe973..5122da3 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -15,7 +15,7 @@ GNU General Public License for more details. *******************************************************************************/ -extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, unsigned int __nocast pri); +extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri); extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags); extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 651f824..b0c9906 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -94,7 +94,7 @@ static inline void *inet_csk_ca(const struct sock *sk) extern struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, - const unsigned int __nocast priority); + const gfp_t priority); enum inet_csk_ack_state_t { ICSK_ACK_SCHED = 1, diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index ecb2b06..3b5559a 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -832,7 +832,7 @@ extern void ip_vs_app_inc_put(struct ip_vs_app *inc); extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff **pskb); extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff **pskb); -extern int ip_vs_skb_replace(struct sk_buff *skb, unsigned int __nocast pri, +extern int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri, char *o_buf, int o_len, char *n_buf, int n_len); extern int ip_vs_app_init(void); extern void ip_vs_app_cleanup(void); diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index 54852ff..00730d2 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -93,7 +93,7 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) return skb->cb[sizeof(skb->cb) - 1]; } -extern struct sock *llc_sk_alloc(int family, unsigned int __nocast priority, +extern struct sock *llc_sk_alloc(int family, gfp_t priority, struct proto *prot); extern void llc_sk_free(struct sock *sk); diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index e1d5ec1..8f24121 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -125,7 +125,7 @@ */ extern struct sock *sctp_get_ctl_sock(void); extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, - sctp_scope_t, unsigned int __nocast gfp, + sctp_scope_t, gfp_t gfp, int flags); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern int sctp_register_pf(struct sctp_pf *, sa_family_t); diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 58462164..1eac3d0 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -181,17 +181,17 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t, int sctp_chunk_iif(const struct sctp_chunk *); struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *, struct sctp_chunk *, - unsigned int __nocast gfp); + gfp_t gfp); __u32 sctp_generate_verification_tag(void); void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag); /* Prototypes for chunk-building functions. */ struct sctp_chunk *sctp_make_init(const struct sctp_association *, const struct sctp_bind_addr *, - unsigned int __nocast gfp, int vparam_len); + gfp_t gfp, int vparam_len); struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *, const struct sctp_chunk *, - const unsigned int __nocast gfp, + const gfp_t gfp, const int unkparam_len); struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *, const struct sctp_chunk *); @@ -265,7 +265,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, struct sctp_endpoint *, struct sctp_association *asoc, void *event_arg, - unsigned int __nocast gfp); + gfp_t gfp); /* 2nd level prototypes */ void sctp_generate_t3_rtx_event(unsigned long peer); @@ -276,7 +276,7 @@ void sctp_ootb_pkt_free(struct sctp_packet *); struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *, const struct sctp_association *, struct sctp_chunk *, - unsigned int __nocast gfp, int *err, + gfp_t gfp, int *err, struct sctp_chunk **err_chk_p); int sctp_addip_addr_config(struct sctp_association *, sctp_param_t, struct sockaddr_storage*, int); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 994009b..9c385b6 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -446,7 +446,7 @@ struct sctp_ssnmap { }; struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, - unsigned int __nocast gfp); + gfp_t gfp); void sctp_ssnmap_free(struct sctp_ssnmap *map); void sctp_ssnmap_clear(struct sctp_ssnmap *map); @@ -947,7 +947,7 @@ struct sctp_transport { }; struct sctp_transport *sctp_transport_new(const union sctp_addr *, - unsigned int __nocast); + gfp_t); void sctp_transport_set_owner(struct sctp_transport *, struct sctp_association *); void sctp_transport_route(struct sctp_transport *, union sctp_addr *, @@ -1095,10 +1095,10 @@ void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port); void sctp_bind_addr_free(struct sctp_bind_addr *); int sctp_bind_addr_copy(struct sctp_bind_addr *dest, const struct sctp_bind_addr *src, - sctp_scope_t scope, unsigned int __nocast gfp, + sctp_scope_t scope, gfp_t gfp, int flags); int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, - unsigned int __nocast gfp); + gfp_t gfp); int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *); @@ -1108,9 +1108,9 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, struct sctp_sock *opt); union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int *addrs_len, - unsigned int __nocast gfp); + gfp_t gfp); int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len, - __u16 port, unsigned int __nocast gfp); + __u16 port, gfp_t gfp); sctp_scope_t sctp_scope(const union sctp_addr *); int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope); @@ -1239,7 +1239,7 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base) } /* These are function signatures for manipulating endpoints. */ -struct sctp_endpoint *sctp_endpoint_new(struct sock *, unsigned int __nocast); +struct sctp_endpoint *sctp_endpoint_new(struct sock *, gfp_t); void sctp_endpoint_free(struct sctp_endpoint *); void sctp_endpoint_put(struct sctp_endpoint *); void sctp_endpoint_hold(struct sctp_endpoint *); @@ -1260,7 +1260,7 @@ int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t, struct sctp_chunk **err_chunk); int sctp_process_init(struct sctp_association *, sctp_cid_t cid, const union sctp_addr *peer, - sctp_init_chunk_t *init, unsigned int __nocast gfp); + sctp_init_chunk_t *init, gfp_t gfp); __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); @@ -1723,7 +1723,7 @@ static inline struct sctp_association *sctp_assoc(struct sctp_ep_common *base) struct sctp_association * sctp_association_new(const struct sctp_endpoint *, const struct sock *, - sctp_scope_t scope, unsigned int __nocast gfp); + sctp_scope_t scope, gfp_t gfp); void sctp_association_free(struct sctp_association *); void sctp_association_put(struct sctp_association *); void sctp_association_hold(struct sctp_association *); @@ -1739,7 +1739,7 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, const union sctp_addr *laddr); struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, const union sctp_addr *address, - const unsigned int __nocast gfp, + const gfp_t gfp, const int peer_state); void sctp_assoc_del_peer(struct sctp_association *asoc, const union sctp_addr *addr); @@ -1764,10 +1764,10 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned); void sctp_assoc_set_primary(struct sctp_association *, struct sctp_transport *); int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *, - unsigned int __nocast); + gfp_t); int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *, struct sctp_cookie*, - unsigned int __nocast gfp); + gfp_t gfp); int sctp_cmp_addr_exact(const union sctp_addr *ss1, const union sctp_addr *ss2); diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 90fe4bf..6c40cfc 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -88,7 +88,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( __u16 error, __u16 outbound, __u16 inbound, - unsigned int __nocast gfp); + gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( const struct sctp_association *asoc, @@ -96,35 +96,35 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( int flags, int state, int error, - unsigned int __nocast gfp); + gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_remote_error( const struct sctp_association *asoc, struct sctp_chunk *chunk, __u16 flags, - unsigned int __nocast gfp); + gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_send_failed( const struct sctp_association *asoc, struct sctp_chunk *chunk, __u16 flags, __u32 error, - unsigned int __nocast gfp); + gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( const struct sctp_association *asoc, __u16 flags, - unsigned int __nocast gfp); + gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_pdapi( const struct sctp_association *asoc, - __u32 indication, unsigned int __nocast gfp); + __u32 indication, gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication( - const struct sctp_association *asoc, unsigned int __nocast gfp); + const struct sctp_association *asoc, gfp_t gfp); struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, struct sctp_chunk *chunk, - unsigned int __nocast gfp); + gfp_t gfp); void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, struct msghdr *); diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h index 1a60c6d..a43c878 100644 --- a/include/net/sctp/ulpqueue.h +++ b/include/net/sctp/ulpqueue.h @@ -62,22 +62,19 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *, void sctp_ulpq_free(struct sctp_ulpq *); /* Add a new DATA chunk for processing. */ -int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, - unsigned int __nocast); +int sctp_ulpq_tail_data(struct sctp_ulpq *, struct sctp_chunk *, gfp_t); /* Add a new event for propagation to the ULP. */ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev); /* Renege previously received chunks. */ -void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, - unsigned int __nocast); +void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t); /* Perform partial delivery. */ -void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, - unsigned int __nocast); +void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t); /* Abort the partial delivery. */ -void sctp_ulpq_abort_pd(struct sctp_ulpq *, unsigned int __nocast); +void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t); /* Clear the partial data delivery condition on this socket. */ int sctp_clear_pd(struct sock *sk); diff --git a/include/net/sock.h b/include/net/sock.h index b644080..ecb7552 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -739,18 +739,18 @@ extern void FASTCALL(release_sock(struct sock *sk)); #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) extern struct sock *sk_alloc(int family, - unsigned int __nocast priority, + gfp_t priority, struct proto *prot, int zero_it); extern void sk_free(struct sock *sk); extern struct sock *sk_clone(const struct sock *sk, - const unsigned int __nocast priority); + const gfp_t priority); extern struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, - unsigned int __nocast priority); + gfp_t priority); extern struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, - unsigned int __nocast priority); + gfp_t priority); extern void sock_wfree(struct sk_buff *skb); extern void sock_rfree(struct sk_buff *skb); @@ -766,7 +766,7 @@ extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, int noblock, int *errcode); extern void *sock_kmalloc(struct sock *sk, int size, - unsigned int __nocast priority); + gfp_t priority); extern void sock_kfree_s(struct sock *sk, void *mem, int size); extern void sk_send_sigurg(struct sock *sk); @@ -1201,7 +1201,7 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk) static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, int size, int mem, - unsigned int __nocast gfp) + gfp_t gfp) { struct sk_buff *skb; int hdr_len; @@ -1224,7 +1224,7 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, static inline struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, - unsigned int __nocast gfp) + gfp_t gfp) { return sk_stream_alloc_pskb(sk, size, 0, gfp); } @@ -1255,7 +1255,7 @@ static inline int sock_writeable(const struct sock *sk) return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf / 2); } -static inline unsigned int __nocast gfp_any(void) +static inline gfp_t gfp_any(void) { return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; } diff --git a/include/net/tcp.h b/include/net/tcp.h index 97af77c..c24339c 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -460,8 +460,7 @@ extern void tcp_send_probe0(struct sock *); extern void tcp_send_partial(struct sock *); extern int tcp_write_wakeup(struct sock *); extern void tcp_send_fin(struct sock *sk); -extern void tcp_send_active_reset(struct sock *sk, - unsigned int __nocast priority); +extern void tcp_send_active_reset(struct sock *sk, gfp_t priority); extern int tcp_send_synack(struct sock *); extern void tcp_push_one(struct sock *, unsigned int mss_now); extern void tcp_send_ack(struct sock *sk); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b6e72f8..5beae1c 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -875,7 +875,7 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig } #endif -struct xfrm_policy *xfrm_policy_alloc(unsigned int __nocast gfp); +struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 0e293fe..4172e68 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h @@ -596,7 +596,7 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, u32 remote_qpn, u16 pkey_index, struct ib_ah *ah, int rmpp_active, int hdr_len, int data_len, - unsigned int __nocast gfp_mask); + gfp_t gfp_mask); /** * ib_free_send_mad - Returns data buffers used to send a MAD. diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index a7555c8..f404fe2 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -285,7 +285,7 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query); int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, struct ib_sa_path_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_path_rec *resp, void *context), @@ -296,7 +296,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_mcmember_rec *resp, void *context), @@ -307,7 +307,7 @@ int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_service_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_service_rec *resp, void *context), @@ -342,7 +342,7 @@ static inline int ib_sa_mcmember_rec_set(struct ib_device *device, u8 port_num, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_mcmember_rec *resp, void *context), @@ -384,7 +384,7 @@ static inline int ib_sa_mcmember_rec_delete(struct ib_device *device, u8 port_num, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, - int timeout_ms, unsigned int __nocast gfp_mask, + int timeout_ms, gfp_t gfp_mask, void (*callback)(int status, struct ib_sa_mcmember_rec *resp, void *context), diff --git a/include/rxrpc/call.h b/include/rxrpc/call.h index 8118731..b86f837 100644 --- a/include/rxrpc/call.h +++ b/include/rxrpc/call.h @@ -203,7 +203,7 @@ extern int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, struct kvec *siov, uint8_t rxhdr_flags, - unsigned int __nocast alloc_flags, + gfp_t alloc_flags, int dup_data, size_t *size_sent); diff --git a/include/rxrpc/message.h b/include/rxrpc/message.h index 983d9f9..b318f27 100644 --- a/include/rxrpc/message.h +++ b/include/rxrpc/message.h @@ -63,7 +63,7 @@ extern int rxrpc_conn_newmsg(struct rxrpc_connection *conn, uint8_t type, int count, struct kvec *diov, - unsigned int __nocast alloc_flags, + gfp_t alloc_flags, struct rxrpc_message **_msg); extern int rxrpc_conn_sendmsg(struct rxrpc_connection *conn, struct rxrpc_message *msg); diff --git a/include/sound/core.h b/include/sound/core.h index 26160ad..6d971a4 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -290,13 +290,13 @@ void snd_memory_init(void); void snd_memory_done(void); int snd_memory_info_init(void); int snd_memory_info_done(void); -void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags); -void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags); -void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags); +void *snd_hidden_kmalloc(size_t size, gfp_t flags); +void *snd_hidden_kzalloc(size_t size, gfp_t flags); +void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags); void snd_hidden_kfree(const void *obj); void *snd_hidden_vmalloc(unsigned long size); void snd_hidden_vfree(void *obj); -char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags); +char *snd_hidden_kstrdup(const char *s, gfp_t flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kzalloc(size, flags) snd_hidden_kzalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) diff --git a/include/sound/driver.h b/include/sound/driver.h index 0d12456..1ec2fae 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -51,7 +51,7 @@ #ifdef CONFIG_SND_DEBUG_MEMORY #include #include -void *snd_wrapper_kmalloc(size_t, unsigned int __nocast); +void *snd_wrapper_kmalloc(size_t, gfp_t); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree diff --git a/kernel/audit.c b/kernel/audit.c index 83096b6..aefa73a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -560,7 +560,7 @@ static void audit_buffer_free(struct audit_buffer *ab) } static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, - unsigned int __nocast gfp_mask, int type) + gfp_t gfp_mask, int type) { unsigned long flags; struct audit_buffer *ab = NULL; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 45a5719..28176d0 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1670,7 +1670,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs) * GFP_USER - only nodes in current tasks mems allowed ok. **/ -int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask) +int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) { int node; /* node that zone z is on */ const struct cpuset *cs; /* current cpuset ancestors */ diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 179baaf..64ab045 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -36,7 +36,7 @@ * struct kfifo with kfree(). */ struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - unsigned int __nocast gfp_mask, spinlock_t *lock) + gfp_t gfp_mask, spinlock_t *lock) { struct kfifo *fifo; @@ -64,7 +64,7 @@ EXPORT_SYMBOL(kfifo_init); * * The size will be rounded-up to a power of 2. */ -struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask, spinlock_t *lock) +struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) { unsigned char *buffer; struct kfifo *ret; diff --git a/kernel/signal.c b/kernel/signal.c index c135f5a..cba193c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -262,7 +262,7 @@ next_signal(struct sigpending *pending, sigset_t *mask) return sig; } -static struct sigqueue *__sigqueue_alloc(struct task_struct *t, unsigned int __nocast flags, +static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, int override_rlimit) { struct sigqueue *q = NULL; diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 6a8bc6e..d1c057e7 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -110,7 +110,7 @@ radix_tree_node_free(struct radix_tree_node *node) * success, return zero, with preemption disabled. On error, return -ENOMEM * with preemption not disabled. */ -int radix_tree_preload(unsigned int __nocast gfp_mask) +int radix_tree_preload(gfp_t gfp_mask) { struct radix_tree_preload *rtp; struct radix_tree_node *node; diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 1b61fce..8a8b3a1 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c @@ -127,7 +127,7 @@ static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, } static struct ts_config *bm_init(const void *pattern, unsigned int len, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct ts_config *conf; struct ts_bm *bm; diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c index ef9779e..ca32112 100644 --- a/lib/ts_fsm.c +++ b/lib/ts_fsm.c @@ -258,7 +258,7 @@ found_match: } static struct ts_config *fsm_init(const void *pattern, unsigned int len, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { int i, err = -EINVAL; struct ts_config *conf; diff --git a/lib/ts_kmp.c b/lib/ts_kmp.c index e45f0f0..7fd4545 100644 --- a/lib/ts_kmp.c +++ b/lib/ts_kmp.c @@ -87,7 +87,7 @@ static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, } static struct ts_config *kmp_init(const void *pattern, unsigned int len, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct ts_config *conf; struct ts_kmp *kmp; diff --git a/mm/highmem.c b/mm/highmem.c index 4009115..90e1861e 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -30,7 +30,7 @@ static mempool_t *page_pool, *isa_page_pool; -static void *page_pool_alloc(unsigned int __nocast gfp_mask, void *data) +static void *page_pool_alloc(gfp_t gfp_mask, void *data) { unsigned int gfp = gfp_mask | (unsigned int) (long) data; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 9033f08..37af443 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -687,7 +687,7 @@ get_vma_policy(struct task_struct *task, struct vm_area_struct *vma, unsigned lo } /* Return a zonelist representing a mempolicy */ -static struct zonelist *zonelist_policy(unsigned int __nocast gfp, struct mempolicy *policy) +static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) { int nd; @@ -751,7 +751,7 @@ static unsigned offset_il_node(struct mempolicy *pol, /* Allocate a page in interleaved policy. Own path because it needs to do special accounting. */ -static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned order, unsigned nid) +static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, unsigned nid) { struct zonelist *zl; struct page *page; @@ -789,7 +789,7 @@ static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned or * Should be called with the mm_sem of the vma hold. */ struct page * -alloc_page_vma(unsigned int __nocast gfp, struct vm_area_struct *vma, unsigned long addr) +alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) { struct mempolicy *pol = get_vma_policy(current, vma, addr); @@ -832,7 +832,7 @@ alloc_page_vma(unsigned int __nocast gfp, struct vm_area_struct *vma, unsigned l * 1) it's ok to take cpuset_sem (can WAIT), and * 2) allocating for current task (not interrupt). */ -struct page *alloc_pages_current(unsigned int __nocast gfp, unsigned order) +struct page *alloc_pages_current(gfp_t gfp, unsigned order) { struct mempolicy *pol = current->mempolicy; diff --git a/mm/mempool.c b/mm/mempool.c index 65f2957..9e377ea 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -112,7 +112,7 @@ EXPORT_SYMBOL(mempool_create_node); * while this function is running. mempool_alloc() & mempool_free() * might be called (eg. from IRQ contexts) while this function executes. */ -int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask) +int mempool_resize(mempool_t *pool, int new_min_nr, gfp_t gfp_mask) { void *element; void **new_elements; @@ -200,7 +200,7 @@ EXPORT_SYMBOL(mempool_destroy); * *never* fails when called from process contexts. (it might * fail if called from an IRQ context.) */ -void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask) +void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask) { void *element; unsigned long flags; @@ -276,7 +276,7 @@ EXPORT_SYMBOL(mempool_free); /* * A commonly used alloc and free fn. */ -void *mempool_alloc_slab(unsigned int __nocast gfp_mask, void *pool_data) +void *mempool_alloc_slab(gfp_t gfp_mask, void *pool_data) { kmem_cache_t *mem = (kmem_cache_t *) pool_data; return kmem_cache_alloc(mem, gfp_mask); diff --git a/mm/nommu.c b/mm/nommu.c index 064d704..0ef241a 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -157,8 +157,7 @@ void vfree(void *addr) kfree(addr); } -void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask, - pgprot_t prot) +void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot) { /* * kmalloc doesn't like __GFP_HIGHMEM for some reason diff --git a/mm/oom_kill.c b/mm/oom_kill.c index ac3bf33..d348b90 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -263,7 +263,7 @@ static struct mm_struct *oom_kill_process(struct task_struct *p) * OR try to be smart about which process to kill. Note that we * don't have to be perfect here, we just have to be good. */ -void out_of_memory(unsigned int __nocast gfp_mask, int order) +void out_of_memory(gfp_t gfp_mask, int order) { struct mm_struct *mm = NULL; task_t * p; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ae29033..cc1fe26 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -671,7 +671,7 @@ void fastcall free_cold_page(struct page *page) free_hot_cold_page(page, 1); } -static inline void prep_zero_page(struct page *page, int order, unsigned int __nocast gfp_flags) +static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) { int i; @@ -686,7 +686,7 @@ static inline void prep_zero_page(struct page *page, int order, unsigned int __n * or two. */ static struct page * -buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags) +buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) { unsigned long flags; struct page *page = NULL; @@ -761,7 +761,7 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark, } static inline int -should_reclaim_zone(struct zone *z, unsigned int gfp_mask) +should_reclaim_zone(struct zone *z, gfp_t gfp_mask) { if (!z->reclaim_pages) return 0; @@ -774,7 +774,7 @@ should_reclaim_zone(struct zone *z, unsigned int gfp_mask) * This is the 'heart' of the zoned buddy allocator. */ struct page * fastcall -__alloc_pages(unsigned int __nocast gfp_mask, unsigned int order, +__alloc_pages(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist) { const int wait = gfp_mask & __GFP_WAIT; @@ -977,7 +977,7 @@ EXPORT_SYMBOL(__alloc_pages); /* * Common helper functions. */ -fastcall unsigned long __get_free_pages(unsigned int __nocast gfp_mask, unsigned int order) +fastcall unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) { struct page * page; page = alloc_pages(gfp_mask, order); @@ -988,7 +988,7 @@ fastcall unsigned long __get_free_pages(unsigned int __nocast gfp_mask, unsigned EXPORT_SYMBOL(__get_free_pages); -fastcall unsigned long get_zeroed_page(unsigned int __nocast gfp_mask) +fastcall unsigned long get_zeroed_page(gfp_t gfp_mask) { struct page * page; diff --git a/mm/page_io.c b/mm/page_io.c index 2e605a1..330e00d 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -19,7 +19,7 @@ #include #include -static struct bio *get_swap_bio(unsigned int __nocast gfp_flags, pgoff_t index, +static struct bio *get_swap_bio(gfp_t gfp_flags, pgoff_t index, struct page *page, bio_end_io_t end_io) { struct bio *bio; diff --git a/mm/shmem.c b/mm/shmem.c index 1f7aeb2..ea064d8 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -921,8 +921,7 @@ shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx) } static inline struct page * -shmem_alloc_page(unsigned int __nocast gfp,struct shmem_inode_info *info, - unsigned long idx) +shmem_alloc_page(gfp_t gfp,struct shmem_inode_info *info, unsigned long idx) { return alloc_page(gfp | __GFP_ZERO); } diff --git a/mm/slab.c b/mm/slab.c index 5cbbdfa6..d05c678 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -650,8 +650,7 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep) return cachep->array[smp_processor_id()]; } -static inline kmem_cache_t *__find_general_cachep(size_t size, - unsigned int __nocast gfpflags) +static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags) { struct cache_sizes *csizep = malloc_sizes; @@ -675,8 +674,7 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, return csizep->cs_cachep; } -kmem_cache_t *kmem_find_general_cachep(size_t size, - unsigned int __nocast gfpflags) +kmem_cache_t *kmem_find_general_cachep(size_t size, gfp_t gfpflags) { return __find_general_cachep(size, gfpflags); } @@ -1185,7 +1183,7 @@ __initcall(cpucache_init); * did not request dmaable memory, we might get it, but that * would be relatively rare and ignorable. */ -static void *kmem_getpages(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid) +static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid) { struct page *page; void *addr; @@ -2048,7 +2046,7 @@ EXPORT_SYMBOL(kmem_cache_destroy); /* Get the memory for a slab management obj. */ static struct slab* alloc_slabmgmt(kmem_cache_t *cachep, void *objp, - int colour_off, unsigned int __nocast local_flags) + int colour_off, gfp_t local_flags) { struct slab *slabp; @@ -2149,7 +2147,7 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp) * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid) +static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid) { struct slab *slabp; void *objp; @@ -2356,7 +2354,7 @@ bad: #define check_slabp(x,y) do { } while(0) #endif -static void *cache_alloc_refill(kmem_cache_t *cachep, unsigned int __nocast flags) +static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags) { int batchcount; struct kmem_list3 *l3; @@ -2456,7 +2454,7 @@ alloc_done: } static inline void -cache_alloc_debugcheck_before(kmem_cache_t *cachep, unsigned int __nocast flags) +cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags) { might_sleep_if(flags & __GFP_WAIT); #if DEBUG @@ -2467,7 +2465,7 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, unsigned int __nocast flags) #if DEBUG static void * cache_alloc_debugcheck_after(kmem_cache_t *cachep, - unsigned int __nocast flags, void *objp, void *caller) + gfp_t flags, void *objp, void *caller) { if (!objp) return objp; @@ -2510,7 +2508,7 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep, #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) #endif -static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) +static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags) { void* objp; struct array_cache *ac; @@ -2528,7 +2526,7 @@ static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast return objp; } -static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) +static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags) { unsigned long save_flags; void* objp; @@ -2787,7 +2785,7 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp) * Allocate an object from this cache. The flags are only relevant * if the cache has no available objects. */ -void *kmem_cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) +void *kmem_cache_alloc(kmem_cache_t *cachep, gfp_t flags) { return __cache_alloc(cachep, flags); } @@ -2848,7 +2846,7 @@ out: * New and improved: it will now make sure that the object gets * put on the correct node list so that there is no false sharing. */ -void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid) +void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid) { unsigned long save_flags; void *ptr; @@ -2875,7 +2873,7 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i } EXPORT_SYMBOL(kmem_cache_alloc_node); -void *kmalloc_node(size_t size, unsigned int __nocast flags, int node) +void *kmalloc_node(size_t size, gfp_t flags, int node) { kmem_cache_t *cachep; @@ -2908,7 +2906,7 @@ EXPORT_SYMBOL(kmalloc_node); * platforms. For example, on i386, it means that the memory must come * from the first 16MB. */ -void *__kmalloc(size_t size, unsigned int __nocast flags) +void *__kmalloc(size_t size, gfp_t flags) { kmem_cache_t *cachep; @@ -2997,7 +2995,7 @@ EXPORT_SYMBOL(kmem_cache_free); * @size: how many bytes of memory are required. * @flags: the type of memory to allocate. */ -void *kzalloc(size_t size, unsigned int __nocast flags) +void *kzalloc(size_t size, gfp_t flags) { void *ret = kmalloc(size, flags); if (ret) @@ -3603,7 +3601,7 @@ unsigned int ksize(const void *objp) * @s: the string to duplicate * @gfp: the GFP mask used in the kmalloc() call when allocating memory */ -char *kstrdup(const char *s, unsigned int __nocast gfp) +char *kstrdup(const char *s, gfp_t gfp) { size_t len; char *buf; diff --git a/mm/swap_state.c b/mm/swap_state.c index adbc2b4..132164f 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -68,7 +68,7 @@ void show_swap_cache_info(void) * but sets SwapCache flag and private instead of mapping and index. */ static int __add_to_swap_cache(struct page *page, swp_entry_t entry, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { int error; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 13c3d82..1150229 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -395,7 +395,7 @@ void *vmap(struct page **pages, unsigned int count, EXPORT_SYMBOL(vmap); -void *__vmalloc_area(struct vm_struct *area, unsigned int __nocast gfp_mask, pgprot_t prot) +void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot) { struct page **pages; unsigned int nr_pages, array_size, i; @@ -446,7 +446,7 @@ fail: * allocator with @gfp_mask flags. Map them into contiguous * kernel virtual space, using a pagetable protection of @prot. */ -void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask, pgprot_t prot) +void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot) { struct vm_struct *area; diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index 71abc99..223c7ad 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c @@ -25,7 +25,7 @@ int atm_charge(struct atm_vcc *vcc,int truesize) struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, - unsigned int __nocast gfp_flags) + gfp_t gfp_flags) { struct sock *sk = sk_atm(vcc); int guess = atm_guess_pdu2truesize(pdu_size); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index d3d6bc5..59b2dd3 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -372,7 +372,7 @@ static struct proto l2cap_proto = { .obj_size = sizeof(struct l2cap_pinfo) }; -static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio) +static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, gfp_t prio) { struct sock *sk; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 173f46e..35adce6 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -229,7 +229,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d) d->rx_credits = RFCOMM_DEFAULT_CREDITS; } -struct rfcomm_dlc *rfcomm_dlc_alloc(unsigned int __nocast prio) +struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio) { struct rfcomm_dlc *d = kmalloc(sizeof(*d), prio); if (!d) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index f49e7e9..a2b30f0 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -284,7 +284,7 @@ static struct proto rfcomm_proto = { .obj_size = sizeof(struct rfcomm_pinfo) }; -static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio) +static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, gfp_t prio) { struct rfcomm_dlc *d; struct sock *sk; diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 1bca860..158a9c4 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -286,7 +286,7 @@ static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *de skb->destructor = rfcomm_wfree; } -static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, unsigned int __nocast priority) +static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority) { if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) { struct sk_buff *skb = alloc_skb(size, priority); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index ce7ab7d..997e42d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -418,7 +418,7 @@ static struct proto sco_proto = { .obj_size = sizeof(struct sco_pinfo) }; -static struct sock *sco_sock_alloc(struct socket *sock, int proto, unsigned int __nocast prio) +static struct sock *sco_sock_alloc(struct socket *sock, int proto, gfp_t prio) { struct sock *sk; diff --git a/net/core/dev.c b/net/core/dev.c index 9066c87..a44eeef 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1132,7 +1132,7 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) #endif /* Keep head the same: replace data */ -int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp_mask) +int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask) { unsigned int size; u8 *data; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0e9431b..af9b151 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -130,7 +130,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) * Buffers may only be allocated from interrupts using a @gfp_mask of * %GFP_ATOMIC. */ -struct sk_buff *__alloc_skb(unsigned int size, unsigned int __nocast gfp_mask, +struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int fclone) { struct sk_buff *skb; @@ -198,7 +198,7 @@ nodata: */ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, unsigned int size, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct sk_buff *skb; u8 *data; @@ -361,7 +361,7 @@ void __kfree_skb(struct sk_buff *skb) * %GFP_ATOMIC. */ -struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask) +struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) { struct sk_buff *n; @@ -500,7 +500,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) * header is going to be modified. Use pskb_copy() instead. */ -struct sk_buff *skb_copy(const struct sk_buff *skb, unsigned int __nocast gfp_mask) +struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) { int headerlen = skb->data - skb->head; /* @@ -539,7 +539,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, unsigned int __nocast gfp_ma * The returned buffer has a reference count of 1. */ -struct sk_buff *pskb_copy(struct sk_buff *skb, unsigned int __nocast gfp_mask) +struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) { /* * Allocate the copy buffer @@ -598,7 +598,7 @@ out: */ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { int i; u8 *data; @@ -689,7 +689,7 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) */ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, int newtailroom, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { /* * Allocate the copy buffer diff --git a/net/core/sock.c b/net/core/sock.c index 928d2a1..1c52fe8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -637,7 +637,7 @@ lenout: * @prot: struct proto associated with this new sock instance * @zero_it: if we should zero the newly allocated sock */ -struct sock *sk_alloc(int family, unsigned int __nocast priority, +struct sock *sk_alloc(int family, gfp_t priority, struct proto *prot, int zero_it) { struct sock *sk = NULL; @@ -704,7 +704,7 @@ void sk_free(struct sock *sk) module_put(owner); } -struct sock *sk_clone(const struct sock *sk, const unsigned int __nocast priority) +struct sock *sk_clone(const struct sock *sk, const gfp_t priority) { struct sock *newsk = sk_alloc(sk->sk_family, priority, sk->sk_prot, 0); @@ -845,7 +845,7 @@ unsigned long sock_i_ino(struct sock *sk) * Allocate a skb from the socket's send buffer. */ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, - unsigned int __nocast priority) + gfp_t priority) { if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { struct sk_buff * skb = alloc_skb(size, priority); @@ -861,7 +861,7 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, * Allocate a skb from the socket's receive buffer. */ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, - unsigned int __nocast priority) + gfp_t priority) { if (force || atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) { struct sk_buff *skb = alloc_skb(size, priority); @@ -876,7 +876,7 @@ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, /* * Allocate a memory block from the socket's option memory buffer. */ -void *sock_kmalloc(struct sock *sk, int size, unsigned int __nocast priority) +void *sock_kmalloc(struct sock *sk, int size, gfp_t priority) { if ((unsigned)size <= sysctl_optmem_max && atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) { diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 6530283..c9a62cc 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -91,7 +91,7 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) } struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, - const unsigned int __nocast priority) + const gfp_t priority) { struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority); diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index 8ca51c9..d0fd6c6 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h @@ -74,7 +74,7 @@ struct sk_buff; #ifdef CONFIG_IP_DCCP_ACKVEC extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, - const unsigned int __nocast priority); + const gfp_t priority); extern void dccp_ackvec_free(struct dccp_ackvec *av); extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, @@ -93,7 +93,7 @@ static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) } #else /* CONFIG_IP_DCCP_ACKVEC */ static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, - const unsigned int __nocast priority) + const gfp_t priority) { return NULL; } diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h index 13ad47b..417d9d8 100644 --- a/net/dccp/ccids/lib/loss_interval.h +++ b/net/dccp/ccids/lib/loss_interval.h @@ -36,7 +36,7 @@ struct dccp_li_hist_entry { static inline struct dccp_li_hist_entry * dccp_li_hist_entry_new(struct dccp_li_hist *hist, - const unsigned int __nocast prio) + const gfp_t prio) { return kmem_cache_alloc(hist->dccplih_slab, prio); } diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index b375ebd..122e967 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h @@ -86,7 +86,7 @@ extern struct dccp_rx_hist_entry * static inline struct dccp_tx_hist_entry * dccp_tx_hist_entry_new(struct dccp_tx_hist *hist, - const unsigned int __nocast prio) + const gfp_t prio) { struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab, prio); @@ -137,7 +137,7 @@ static inline struct dccp_rx_hist_entry * const struct sock *sk, const u32 ndp, const struct sk_buff *skb, - const unsigned int __nocast prio) + const gfp_t prio) { struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab, prio); diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 34d4128..1186dc4 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -452,8 +452,7 @@ static struct proto dn_proto = { .obj_size = sizeof(struct dn_sock), }; -static struct sock *dn_alloc_sock(struct socket *sock, - unsigned int __nocast gfp) +static struct sock *dn_alloc_sock(struct socket *sock, gfp_t gfp) { struct dn_scp *scp; struct sock *sk = sk_alloc(PF_DECnet, gfp, &dn_proto, 1); @@ -805,8 +804,7 @@ static int dn_auto_bind(struct socket *sock) return rv; } -static int dn_confirm_accept(struct sock *sk, long *timeo, - unsigned int __nocast allocation) +static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) { struct dn_scp *scp = DN_SK(sk); DEFINE_WAIT(wait); diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index cd08244..c96c767 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c @@ -117,8 +117,7 @@ try_again: * The eventual aim is for each socket to have a cached header size * for its outgoing packets, and to set hdr from this when sk != NULL. */ -struct sk_buff *dn_alloc_skb(struct sock *sk, int size, - unsigned int __nocast pri) +struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri) { struct sk_buff *skb; int hdr = 64; @@ -212,7 +211,7 @@ static void dn_nsp_rtt(struct sock *sk, long rtt) * Returns: The number of times the packet has been sent previously */ static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, - unsigned int __nocast gfp) + gfp_t gfp) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct sk_buff *skb2; @@ -353,7 +352,7 @@ static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *sk } void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, - unsigned int __nocast gfp, int oth) + gfp_t gfp, int oth) { struct dn_scp *scp = DN_SK(sk); struct dn_skb_cb *cb = DN_SKB_CB(skb); @@ -520,7 +519,7 @@ static int dn_nsp_retrans_conn_conf(struct sock *sk) return 0; } -void dn_send_conn_conf(struct sock *sk, unsigned int __nocast gfp) +void dn_send_conn_conf(struct sock *sk, gfp_t gfp) { struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb = NULL; @@ -552,7 +551,7 @@ void dn_send_conn_conf(struct sock *sk, unsigned int __nocast gfp) static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, - unsigned short reason, unsigned int __nocast gfp, + unsigned short reason, gfp_t gfp, struct dst_entry *dst, int ddl, unsigned char *dd, __u16 rem, __u16 loc) { @@ -595,7 +594,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, - unsigned short reason, unsigned int __nocast gfp) + unsigned short reason, gfp_t gfp) { struct dn_scp *scp = DN_SK(sk); int ddl = 0; @@ -616,7 +615,7 @@ void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, { struct dn_skb_cb *cb = DN_SKB_CB(skb); int ddl = 0; - unsigned int __nocast gfp = GFP_ATOMIC; + gfp_t gfp = GFP_ATOMIC; dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl, NULL, cb->src_port, cb->dst_port); @@ -628,7 +627,7 @@ void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval) struct dn_scp *scp = DN_SK(sk); struct sk_buff *skb; unsigned char *ptr; - unsigned int __nocast gfp = GFP_ATOMIC; + gfp_t gfp = GFP_ATOMIC; if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL) return; @@ -663,8 +662,7 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg) unsigned char menuver; struct dn_skb_cb *cb; unsigned char type = 1; - unsigned int __nocast allocation = - (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC; + gfp_t allocation = (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC; struct sk_buff *skb = dn_alloc_skb(sk, 200, allocation); if (!skb) diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index ecdf9f7..eed07bb 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -207,7 +207,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) } static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { struct ieee80211_txb *txb; int i; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index fe3c6d3..94468a7 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -494,7 +494,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_prune); struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, - const unsigned int __nocast priority) + const gfp_t priority) { struct sock *newsk = sk_clone(sk, priority); diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index b942ff3..fc6f95a 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -604,7 +604,7 @@ static struct file_operations ip_vs_app_fops = { /* * Replace a segment of data with a new segment */ -int ip_vs_skb_replace(struct sk_buff *skb, unsigned int __nocast pri, +int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri, char *o_buf, int o_len, char *n_buf, int n_len) { struct iphdr *iph; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c5b911f..8225e42 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1610,7 +1610,7 @@ void tcp_send_fin(struct sock *sk) * was unread data in the receive queue. This behavior is recommended * by draft-ietf-tcpimpl-prob-03.txt section 3.10. -DaveM */ -void tcp_send_active_reset(struct sock *sk, unsigned int __nocast priority) +void tcp_send_active_reset(struct sock *sk, gfp_t priority) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; diff --git a/net/key/af_key.c b/net/key/af_key.c index bbf0f69..3903168 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -185,7 +185,7 @@ static int pfkey_release(struct socket *sock) } static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - unsigned int __nocast allocation, struct sock *sk) + gfp_t allocation, struct sock *sk) { int err = -ENOBUFS; @@ -217,7 +217,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, #define BROADCAST_ONE 1 #define BROADCAST_REGISTERED 2 #define BROADCAST_PROMISC_ONLY 4 -static int pfkey_broadcast(struct sk_buff *skb, unsigned int __nocast allocation, +static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, int broadcast_flags, struct sock *one_sk) { struct sock *sk; @@ -1417,7 +1417,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, } static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, - unsigned int __nocast allocation) + gfp_t allocation) { struct sk_buff *skb; struct sadb_msg *hdr; diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 042b24a..c761c15 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -867,8 +867,7 @@ static void llc_sk_init(struct sock* sk) * Allocates a LLC sock and initializes it. Returns the new LLC sock * or %NULL if there's no memory available for one */ -struct sock *llc_sk_alloc(int family, unsigned int __nocast priority, - struct proto *prot) +struct sock *llc_sk_alloc(int family, gfp_t priority, struct proto *prot) { struct sock *sk = sk_alloc(family, priority, prot, 1); diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 34d6719..1caaca0 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -195,8 +195,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) { - unsigned int __nocast allocation = - in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; + gfp_t allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; int err = 0; NETLINK_CB(skb).dst_group = group; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a64e1d5..678c3f2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -758,7 +758,7 @@ void netlink_detachskb(struct sock *sk, struct sk_buff *skb) } static inline struct sk_buff *netlink_trim(struct sk_buff *skb, - unsigned int __nocast allocation) + gfp_t allocation) { int delta; @@ -880,7 +880,7 @@ out: } int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, - u32 group, unsigned int __nocast allocation) + u32 group, gfp_t allocation) { struct netlink_broadcast_data info; struct hlist_node *node; diff --git a/net/rxrpc/call.c b/net/rxrpc/call.c index 86f7770..c4aeb7d 100644 --- a/net/rxrpc/call.c +++ b/net/rxrpc/call.c @@ -1923,7 +1923,7 @@ int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, struct kvec *siov, u8 rxhdr_flags, - unsigned int __nocast alloc_flags, + gfp_t alloc_flags, int dup_data, size_t *size_sent) { diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c index be4b2be..2ba14a7 100644 --- a/net/rxrpc/connection.c +++ b/net/rxrpc/connection.c @@ -522,7 +522,7 @@ int rxrpc_conn_newmsg(struct rxrpc_connection *conn, uint8_t type, int dcount, struct kvec diov[], - unsigned int __nocast alloc_flags, + gfp_t alloc_flags, struct rxrpc_message **_msg) { struct rxrpc_message *msg; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5b24ae0..12b0f58 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -71,7 +71,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a const struct sctp_endpoint *ep, const struct sock *sk, sctp_scope_t scope, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_sock *sp; int i; @@ -273,7 +273,7 @@ fail_init: struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, const struct sock *sk, sctp_scope_t scope, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_association *asoc; @@ -479,7 +479,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, /* Add a transport address to an association. */ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, const union sctp_addr *addr, - const unsigned int __nocast gfp, + const gfp_t gfp, const int peer_state) { struct sctp_transport *peer; @@ -1231,7 +1231,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) * local endpoint and the remote peer. */ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, - unsigned int __nocast gfp) + gfp_t gfp) { sctp_scope_t scope; int flags; @@ -1254,7 +1254,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, /* Build the association's bind address list from the cookie. */ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc, struct sctp_cookie *cookie, - unsigned int __nocast gfp) + gfp_t gfp) { int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length); int var_size3 = cookie->raw_addr_list_len; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f715497..2b96262 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -53,7 +53,7 @@ /* Forward declarations for internal helpers. */ static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *, - sctp_scope_t scope, unsigned int __nocast gfp, + sctp_scope_t scope, gfp_t gfp, int flags); static void sctp_bind_addr_clean(struct sctp_bind_addr *); @@ -64,7 +64,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *); */ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, const struct sctp_bind_addr *src, - sctp_scope_t scope, unsigned int __nocast gfp, + sctp_scope_t scope, gfp_t gfp, int flags) { struct sctp_sockaddr_entry *addr; @@ -146,7 +146,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp) /* Add an address to the bind address list in the SCTP_bind_addr structure. */ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_sockaddr_entry *addr; @@ -200,7 +200,7 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) */ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int *addrs_len, - unsigned int __nocast gfp) + gfp_t gfp) { union sctp_params addrparms; union sctp_params retval; @@ -252,7 +252,7 @@ end_raw: * address parameters). */ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, - int addrs_len, __u16 port, unsigned int __nocast gfp) + int addrs_len, __u16 port, gfp_t gfp) { union sctp_addr_param *rawaddr; struct sctp_paramhdr *param; @@ -350,7 +350,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, /* Copy out addresses from the global local address list. */ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, union sctp_addr *addr, - sctp_scope_t scope, unsigned int __nocast gfp, + sctp_scope_t scope, gfp_t gfp, int flags) { int error = 0; diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 61da293..83ef411 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -62,7 +62,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) } /* Allocate and initialize datamsg. */ -SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(unsigned int __nocast gfp) +SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp) { struct sctp_datamsg *msg; msg = kmalloc(sizeof(struct sctp_datamsg), gfp); diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index e22ccd6..96984f7 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -68,7 +68,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep); */ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, struct sock *sk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_sock *sp = sctp_sk(sk); memset(ep, 0, sizeof(struct sctp_endpoint)); @@ -138,8 +138,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, /* Create a sctp_endpoint with all that boring stuff initialized. * Returns NULL if there isn't enough memory. */ -struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, - unsigned int __nocast gfp) +struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp) { struct sctp_endpoint *ep; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index f01d1c9..26de4d3 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -219,7 +219,7 @@ static void sctp_free_local_addr_list(void) /* Copy the local addresses which are valid for 'scope' into 'bp'. */ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, - unsigned int __nocast gfp, int copy_flags) + gfp_t gfp, int copy_flags) { struct sctp_sockaddr_entry *addr; int error = 0; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 3868a8d..10e82ec 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -78,7 +78,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, static int sctp_process_param(struct sctp_association *asoc, union sctp_params param, const union sctp_addr *peer_addr, - unsigned int __nocast gfp); + gfp_t gfp); /* What was the inbound interface for this chunk? */ int sctp_chunk_iif(const struct sctp_chunk *chunk) @@ -174,7 +174,7 @@ void sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code, */ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, const struct sctp_bind_addr *bp, - unsigned int __nocast gfp, int vparam_len) + gfp_t gfp, int vparam_len) { sctp_inithdr_t init; union sctp_params addrs; @@ -261,7 +261,7 @@ nodata: struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, const struct sctp_chunk *chunk, - unsigned int __nocast gfp, int unkparam_len) + gfp_t gfp, int unkparam_len) { sctp_inithdr_t initack; struct sctp_chunk *retval; @@ -1234,7 +1234,7 @@ void sctp_chunk_assign_tsn(struct sctp_chunk *chunk) /* Create a CLOSED association to use with an incoming packet. */ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sctp_chunk *chunk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_association *asoc; struct sk_buff *skb; @@ -1349,7 +1349,7 @@ nodata: struct sctp_association *sctp_unpack_cookie( const struct sctp_endpoint *ep, const struct sctp_association *asoc, - struct sctp_chunk *chunk, unsigned int __nocast gfp, + struct sctp_chunk *chunk, gfp_t gfp, int *error, struct sctp_chunk **errp) { struct sctp_association *retval = NULL; @@ -1814,7 +1814,7 @@ int sctp_verify_init(const struct sctp_association *asoc, */ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, const union sctp_addr *peer_addr, - sctp_init_chunk_t *peer_init, unsigned int __nocast gfp) + sctp_init_chunk_t *peer_init, gfp_t gfp) { union sctp_params param; struct sctp_transport *transport; @@ -1985,7 +1985,7 @@ nomem: static int sctp_process_param(struct sctp_association *asoc, union sctp_params param, const union sctp_addr *peer_addr, - unsigned int __nocast gfp) + gfp_t gfp) { union sctp_addr addr; int i; diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 39c970b..f84173e 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -63,7 +63,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, - unsigned int __nocast gfp); + gfp_t gfp); static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, sctp_state_t state, struct sctp_endpoint *ep, @@ -71,7 +71,7 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, - unsigned int __nocast gfp); + gfp_t gfp); /******************************************************************** * Helper functions @@ -498,7 +498,7 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, struct sctp_association *asoc, struct sctp_chunk *chunk, sctp_init_chunk_t *peer_init, - unsigned int __nocast gfp) + gfp_t gfp) { int error; @@ -853,7 +853,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, struct sctp_endpoint *ep, struct sctp_association *asoc, void *event_arg, - unsigned int __nocast gfp) + gfp_t gfp) { sctp_cmd_seq_t commands; const sctp_sm_table_entry_t *state_fn; @@ -898,7 +898,7 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, - unsigned int __nocast gfp) + gfp_t gfp) { int error; @@ -986,7 +986,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, void *event_arg, sctp_disposition_t status, sctp_cmd_seq_t *commands, - unsigned int __nocast gfp) + gfp_t gfp) { int error = 0; int force; diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c index 25037da..cbe2513 100644 --- a/net/sctp/ssnmap.c +++ b/net/sctp/ssnmap.c @@ -58,7 +58,7 @@ static inline size_t sctp_ssnmap_size(__u16 in, __u16 out) * Allocate room to store at least 'len' contiguous TSNs. */ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_ssnmap *retval; int size; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d2f04eb..6bc2720 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -57,7 +57,7 @@ /* Initialize a new transport from provided memory. */ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, const union sctp_addr *addr, - unsigned int __nocast gfp) + gfp_t gfp) { /* Copy in the address. */ peer->ipaddr = *addr; @@ -122,7 +122,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, /* Allocate and initialize a new transport. */ struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_transport *transport; diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 0abd510..057e7fa 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -74,7 +74,7 @@ SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) /* Create a new sctp_ulpevent. */ SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_ulpevent *event; struct sk_buff *skb; @@ -136,7 +136,7 @@ static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event) struct sctp_ulpevent *sctp_ulpevent_make_assoc_change( const struct sctp_association *asoc, __u16 flags, __u16 state, __u16 error, __u16 outbound, - __u16 inbound, unsigned int __nocast gfp) + __u16 inbound, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_assoc_change *sac; @@ -237,7 +237,7 @@ fail: struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( const struct sctp_association *asoc, const struct sockaddr_storage *aaddr, - int flags, int state, int error, unsigned int __nocast gfp) + int flags, int state, int error, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_paddr_change *spc; @@ -350,7 +350,7 @@ fail: */ struct sctp_ulpevent *sctp_ulpevent_make_remote_error( const struct sctp_association *asoc, struct sctp_chunk *chunk, - __u16 flags, unsigned int __nocast gfp) + __u16 flags, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_remote_error *sre; @@ -448,7 +448,7 @@ fail: */ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( const struct sctp_association *asoc, struct sctp_chunk *chunk, - __u16 flags, __u32 error, unsigned int __nocast gfp) + __u16 flags, __u32 error, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_send_failed *ssf; @@ -557,7 +557,7 @@ fail: */ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event( const struct sctp_association *asoc, - __u16 flags, unsigned int __nocast gfp) + __u16 flags, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_shutdown_event *sse; @@ -620,7 +620,7 @@ fail: * 5.3.1.6 SCTP_ADAPTION_INDICATION */ struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication( - const struct sctp_association *asoc, unsigned int __nocast gfp) + const struct sctp_association *asoc, gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_adaption_event *sai; @@ -657,7 +657,7 @@ fail: */ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, struct sctp_chunk *chunk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_ulpevent *event = NULL; struct sk_buff *skb; @@ -719,7 +719,7 @@ fail: */ struct sctp_ulpevent *sctp_ulpevent_make_pdapi( const struct sctp_association *asoc, __u32 indication, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_pdapi_event *pd; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index ec2c857..2080b2d 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -100,7 +100,7 @@ void sctp_ulpq_free(struct sctp_ulpq *ulpq) /* Process an incoming DATA chunk. */ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sk_buff_head temp; sctp_data_chunk_t *hdr; @@ -792,7 +792,7 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed) /* Partial deliver the first message as there is pressure on rwnd. */ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_ulpevent *event; struct sctp_association *asoc; @@ -816,7 +816,7 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, /* Renege some packets to make room for an incoming chunk. */ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, - unsigned int __nocast gfp) + gfp_t gfp) { struct sctp_association *asoc; __u16 needed, freed; @@ -855,7 +855,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, /* Notify the application if an association is aborted and in * partial delivery mode. Send up any pending received messages. */ -void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, unsigned int __nocast gfp) +void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) { struct sctp_ulpevent *ev = NULL; struct sock *sk; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ade730e..54e60a6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -719,7 +719,7 @@ static void rpc_async_schedule(void *arg) void * rpc_malloc(struct rpc_task *task, size_t size) { - unsigned int __nocast gfp; + gfp_t gfp; if (task->tk_flags & RPC_TASK_SWAPPER) gfp = GFP_ATOMIC; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 061b44c..cbb0ba3 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -225,7 +225,7 @@ expired: * SPD calls. */ -struct xfrm_policy *xfrm_policy_alloc(unsigned int __nocast gfp) +struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) { struct xfrm_policy *policy; diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 91124dd..e72cec7 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -106,7 +106,7 @@ struct snd_mem_list { static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, - unsigned int __nocast flags) + gfp_t flags) { void *ret; u64 dma_mask, coherent_dma_mask; diff --git a/sound/core/memory.c b/sound/core/memory.c index 8fa888f..7d8e2ee 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -89,7 +89,7 @@ void snd_memory_done(void) } } -static void *__snd_kmalloc(size_t size, unsigned int __nocast flags, void *caller) +static void *__snd_kmalloc(size_t size, gfp_t flags, void *caller) { unsigned long cpu_flags; struct snd_alloc_track *t; @@ -111,12 +111,12 @@ static void *__snd_kmalloc(size_t size, unsigned int __nocast flags, void *calle } #define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); -void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags) +void *snd_hidden_kmalloc(size_t size, gfp_t flags) { return _snd_kmalloc(size, flags); } -void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags) +void *snd_hidden_kzalloc(size_t size, gfp_t flags) { void *ret = _snd_kmalloc(size, flags); if (ret) @@ -125,7 +125,7 @@ void *snd_hidden_kzalloc(size_t size, unsigned int __nocast flags) } EXPORT_SYMBOL(snd_hidden_kzalloc); -void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags) +void *snd_hidden_kcalloc(size_t n, size_t size, gfp_t flags) { void *ret = NULL; if (n != 0 && size > INT_MAX / n) @@ -190,7 +190,7 @@ void snd_hidden_vfree(void *obj) snd_wrapper_vfree(obj); } -char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags) +char *snd_hidden_kstrdup(const char *s, gfp_t flags) { int len; char *buf; diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c index b3cee09..67c24c8 100644 --- a/sound/core/seq/instr/ainstr_iw.c +++ b/sound/core/seq/instr/ainstr_iw.c @@ -58,7 +58,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype, iwffff_xenv_t *ex, char __user **data, long *len, - unsigned int __nocast gfp_mask) + gfp_t gfp_mask) { __u32 stype; iwffff_env_record_t *rp, *rp_last; diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c index 508e6d6..296b716 100644 --- a/sound/core/wrappers.c +++ b/sound/core/wrappers.c @@ -27,7 +27,7 @@ #include #ifdef CONFIG_SND_DEBUG_MEMORY -void *snd_wrapper_kmalloc(size_t size, unsigned int __nocast flags) +void *snd_wrapper_kmalloc(size_t size, gfp_t flags) { return kmalloc(size, flags); } -- cgit v0.10.2 From 2e457ef667158840c1be511f5d10dd42c6dbbe46 Mon Sep 17 00:00:00 2001 From: Sven Hartge Date: Sat, 8 Oct 2005 21:12:04 -0700 Subject: [SPARC64]: Fix compile error in irq.c irq.c is missing the inclusion of asm/io.h, which causes readb() and writeb() the be undefined. Signed-off-by: Sven Hartge Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index c9b6916..233526b 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From ce80cc14810fbd78fa70c15c7e16a0b26d462fc6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 10 Oct 2005 09:48:10 +0100 Subject: [ARM] Update mach-types Signed-off-by: Russell King diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 6d3a79e..ae7c64b 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -2,11 +2,17 @@ # # This file is linux/arch/arm/tools/mach-types # +# Up to date versions of this file can be obtained from: +# +# http://www.arm.linux.org.uk/developer/machines/?action=download +# # Please do not send patches to this file; it is automatically generated! # To add an entry into this database, please see Documentation/arm/README, -# or contact rmk@arm.linux.org.uk +# or visit: +# +# http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Thu Jun 23 20:19:33 2005 +# Last update: Mon Oct 10 09:46:25 2005 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -421,7 +427,7 @@ mt02 MACH_MT02 MT02 410 mport3s MACH_MPORT3S MPORT3S 411 ra_alpha MACH_RA_ALPHA RA_ALPHA 412 xcep MACH_XCEP XCEP 413 -arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414 +arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414 stargate MACH_STARGATE STARGATE 415 armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 elroy_jack MACH_ELROY_JACK ELROY_JACK 417 @@ -454,7 +460,7 @@ esl_sarva MACH_ESL_SARVA ESL_SARVA 443 xm250 MACH_XM250 XM250 444 t6tc1xb MACH_T6TC1XB T6TC1XB 445 ess710 MACH_ESS710 ESS710 446 -mx3ads MACH_MX3ADS MX3ADS 447 +mx31ads MACH_MX3ADS MX3ADS 447 himalaya MACH_HIMALAYA HIMALAYA 448 bolfenk MACH_BOLFENK BOLFENK 449 at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 @@ -787,3 +793,79 @@ ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778 tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779 universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780 hicoarm9 MACH_HICOARM9 HICOARM9 781 +pnx4008 MACH_PNX4008 PNX4008 782 +kws6000 MACH_KWS6000 KWS6000 783 +portux920t MACH_PORTUX920T PORTUX920T 784 +ez_x5 MACH_EZ_X5 EZ_X5 785 +omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786 +cpuat91 MACH_CPUAT91 CPUAT91 787 +rea9200 MACH_REA9200 REA9200 788 +acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789 +ixp425 MACH_IXP425 IXP425 790 +argonplusodyssey MACH_ODYSSEY ODYSSEY 791 +perch MACH_PERCH PERCH 792 +eis05r1 MACH_EIS05R1 EIS05R1 793 +pepperpad MACH_PEPPERPAD PEPPERPAD 794 +sb3010 MACH_SB3010 SB3010 795 +rm9200 MACH_RM9200 RM9200 796 +dma03 MACH_DMA03 DMA03 797 +road_s101 MACH_ROAD_S101 ROAD_S101 798 +iq_nextgen_a MACH_IQ_NEXTGEN_A IQ_NEXTGEN_A 799 +iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800 +iq_nextgen_c MACH_IQ_NEXTGEN_C IQ_NEXTGEN_C 801 +iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802 +iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803 +mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804 +cybertracker MACH_CYBERTRACKER CYBERTRACKER 805 +gesbc931x MACH_GESBC931X GESBC931X 806 +centipad MACH_CENTIPAD CENTIPAD 807 +armsoc MACH_ARMSOC ARMSOC 808 +se4200 MACH_SE4200 SE4200 809 +ems197a MACH_EMS197A EMS197A 810 +micro9 MACH_MICRO9 MICRO9 811 +micro9l MACH_MICRO9L MICRO9L 812 +uc5471dsp MACH_UC5471DSP UC5471DSP 813 +sj5471eng MACH_SJ5471ENG SJ5471ENG 814 +none MACH_CMPXA26X CMPXA26X 815 +nc MACH_NC NC 816 +omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817 +ajax52x MACH_AJAX52X AJAX52X 818 +siriustar MACH_SIRIUSTAR SIRIUSTAR 819 +iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820 +at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821 +biosafe MACH_BIOSAFE BIOSAFE 822 +mp1000 MACH_MP1000 MP1000 823 +parsy MACH_PARSY PARSY 824 +ccxp270 MACH_CCXP CCXP 825 +omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826 +realview_eb MACH_REALVIEW_EB REALVIEW_EB 827 +samoa MACH_SAMOA SAMOA 828 +t3xscale MACH_T3XSCALE T3XSCALE 829 +i878 MACH_I878 I878 830 +borzoi MACH_BORZOI BORZOI 831 +gecko MACH_GECKO GECKO 832 +ds101 MACH_DS101 DS101 833 +omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834 +xscale_palmld MACH_XSCALE_PALMLD XSCALE_PALMLD 835 +cc9c MACH_CC9C CC9C 836 +sbc1670 MACH_SBC1670 SBC1670 837 +ixdp28x5 MACH_IXDP28X5 IXDP28X5 838 +omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839 +ml696k MACH_ML696K ML696K 840 +arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841 +osiris MACH_OSIRIS OSIRIS 842 +maestro MACH_MAESTRO MAESTRO 843 +tunge2 MACH_TUNGE2 TUNGE2 844 +ixbbm MACH_IXBBM IXBBM 845 +mx27 MACH_MX27 MX27 846 +ax8004 MACH_AX8004 AX8004 847 +at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848 +loft MACH_LOFT LOFT 849 +magpie MACH_MAGPIE MAGPIE 850 +mx21 MACH_MX21 MX21 851 +mb87m3400 MACH_MB87M3400 MB87M3400 852 +mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853 +davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854 +htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855 +tpad MACH_TPAD TPAD 856 +roverp3 MACH_ROVERP3 ROVERP3 857 -- cgit v0.10.2 From 86371d071bc38a181984b01d323b6172a4b7bb1f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 10 Oct 2005 10:17:42 +0100 Subject: [ARM] 2957/1: imx UART Error handling Patch from Sascha Hauer Fix error path in imx_startup. Signed-off-by: Giancarlo Formicuccia Signed-off-by: Sascha Hauer Signed-off-by: Russell King diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4e1e80a..53e0323 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -383,11 +383,11 @@ static int imx_startup(struct uart_port *port) */ retval = request_irq(sport->rxirq, imx_rxint, 0, DRIVER_NAME, sport); - if (retval) goto error_out2; + if (retval) goto error_out1; retval = request_irq(sport->txirq, imx_txint, 0, "imx-uart", sport); - if (retval) goto error_out1; + if (retval) goto error_out2; /* * Finally, clear and enable interrupts @@ -406,10 +406,9 @@ static int imx_startup(struct uart_port *port) return 0; -error_out1: - free_irq(sport->rxirq, sport); error_out2: - free_irq(sport->txirq, sport); + free_irq(sport->rxirq, sport); +error_out1: return retval; } -- cgit v0.10.2 From 79d13b62ef9da84d3ba551caac42d6107e57208f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 10 Oct 2005 10:17:43 +0100 Subject: [ARM] 2958/1: fix definition in imx-regs.h Patch from Sascha Hauer Fix PD7_AF_UART2_DTR definition Signed-off-by: Giancarlo Formicuccia Signed-off-by: Sascha Hauer Signed-off-by: Russell King diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h index 229f700..a6912b3 100644 --- a/include/asm-arm/arch-imx/imx-regs.h +++ b/include/asm-arm/arch-imx/imx-regs.h @@ -215,7 +215,7 @@ #define PC31_AOUT_UART3_RX ( GPIO_GIUS | GPIO_PORTC | GPIO_IN | 31) #define PD6_PF_LSCLK ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 6 ) #define PD7_PF_REV ( GPIO_PORTD | GPIO_PF | 7 ) -#define PD7_AF_UART2_DTR ( GPIO_PORTD | GPIO_IN | GPIO_AF | 7 ) +#define PD7_AF_UART2_DTR ( GPIO_GIUS | GPIO_PORTD | GPIO_IN | GPIO_AF | 7 ) #define PD7_AIN_SPI2_SCLK ( GPIO_GIUS | GPIO_PORTD | GPIO_AIN | 7 ) #define PD8_PF_CLS ( GPIO_PORTD | GPIO_PF | 8 ) #define PD8_AF_UART2_DCD ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 8 ) -- cgit v0.10.2 From 19da83f632d235fff9f94671d2e2cf87d27a2446 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Mon, 10 Oct 2005 10:17:44 +0100 Subject: [ARM] 2959/1: Add test for invalid LDRD/STRD Rd cases in ARM alignment handler Patch from George G. Davis Add test for invalid LDRD/STRD Rd cases in ARM alignment handler and restore SWP printk KERN_ERR. Signed-off-by: Steve Longerbeam Signed-off-by: George G. Davis Signed-off-by: Russell King diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 4b39d86..f35e69e 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -330,6 +330,9 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, { unsigned int rd = RD_BITS(instr); + if (((rd & 1) == 1) || (rd == 14)) + goto bad; + ai_dword += 1; if (user_mode(regs)) @@ -361,7 +364,8 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, } return TYPE_LDST; - + bad: + return TYPE_ERROR; fault: return TYPE_FAULT; } @@ -663,6 +667,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */ (instr & 0x001000f0) == 0x000000f0) /* STRD */ handler = do_alignment_ldrdstrd; + else if ((instr & 0x01f00ff0) == 0x01000090) /* SWP */ + goto swp; else goto bad; break; @@ -733,6 +739,9 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) do_bad_area(current, current->mm, addr, fsr, regs); return 0; + swp: + printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); + bad: /* * Oops, we didn't handle the instruction. -- cgit v0.10.2 From 97b8e00e8538c9eb23983545d665ffd7052ccedb Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 10 Oct 2005 10:17:44 +0100 Subject: [ARM] 2960/1: collie: Add missing scoop call parameters Patch from Richard Purdie Add some missing parameters from the scoop calls on collie. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 25d6a4e..6ecab7e 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -111,11 +111,11 @@ static struct mtd_partition collie_partitions[] = { static void collie_set_vpp(int vpp) { - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR) | COLLIE_SCP_VPEN); if (vpp) - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) | COLLIE_SCP_VPEN); else - write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); + write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) & ~COLLIE_SCP_VPEN); } static struct flash_platform_data collie_flash_data = { -- cgit v0.10.2 From 1036260e93a907a0143efa31bf05be1f3271eb90 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 10 Oct 2005 10:17:45 +0100 Subject: [ARM] 2961/1: corgi: Add missing include Patch from Richard Purdie Add a missing include from corgi.c Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index be37586..60c8b9d 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include -- cgit v0.10.2 From 7c3989885cfd37d237eca97832b712a7ffbbf40c Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Mon, 10 Oct 2005 10:20:06 +0100 Subject: [ARM] 2962/1: scoop: Allow GPIO pin suspend state to be specified Patch from Richard Purdie Allow the GPIO pin suspend states to be specified for SCOOP devices. This is needed for correct operation on the spitz platform. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index d3a04c2..9e5245c 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -26,6 +26,8 @@ struct scoop_pcmcia_dev *scoop_devs; struct scoop_dev { void *base; spinlock_t scoop_lock; + unsigned short suspend_clr; + unsigned short suspend_set; u32 scoop_gpwr; }; @@ -90,14 +92,24 @@ EXPORT_SYMBOL(reset_scoop); EXPORT_SYMBOL(read_scoop_reg); EXPORT_SYMBOL(write_scoop_reg); +static void check_scoop_reg(struct scoop_dev *sdev) +{ + unsigned short mcr; + + mcr = SCOOP_REG(sdev->base, SCOOP_MCR); + if ((mcr & 0x100) == 0) + SCOOP_REG(sdev->base, SCOOP_MCR) = 0x0101; +} + #ifdef CONFIG_PM static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level) { if (level == SUSPEND_POWER_DOWN) { struct scoop_dev *sdev = dev_get_drvdata(dev); - sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR); - SCOOP_REG(sdev->base,SCOOP_GPWR) = 0; + check_scoop_reg(sdev); + sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR); + SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set; } return 0; } @@ -107,6 +119,7 @@ static int scoop_resume(struct device *dev, uint32_t level) if (level == RESUME_POWER_ON) { struct scoop_dev *sdev = dev_get_drvdata(dev); + check_scoop_reg(sdev); SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr; } return 0; @@ -151,6 +164,9 @@ int __init scoop_probe(struct device *dev) SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; + devptr->suspend_clr = inf->suspend_clr; + devptr->suspend_set = inf->suspend_set; + return 0; } diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h index 527404b..a8f1013 100644 --- a/include/asm-arm/hardware/scoop.h +++ b/include/asm-arm/hardware/scoop.h @@ -38,6 +38,8 @@ struct scoop_config { unsigned short io_out; unsigned short io_dir; + unsigned short suspend_clr; + unsigned short suspend_set; }; /* Structure for linking scoop devices to PCMCIA sockets */ -- cgit v0.10.2 From cdfc8f5079fdd18f6cb8097aa4235704d1155ec5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 10:20:06 +0100 Subject: [ARM] 2963/1: S3C2410 - add .owner field to device_driver Patch from Ben Dooks Add initialisation of .owner field so that the device driver can be referenced to the module that owns it. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c index ed867db..e1a90d9 100644 --- a/drivers/char/s3c2410-rtc.c +++ b/drivers/char/s3c2410-rtc.c @@ -564,6 +564,7 @@ static int s3c2410_rtc_resume(struct device *dev, u32 level) static struct device_driver s3c2410_rtcdrv = { .name = "s3c2410-rtc", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2410_rtc_probe, .remove = s3c2410_rtc_remove, -- cgit v0.10.2 From 7dead80cbee3259e3a9f25bfc65c8dc769a19e0e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Oct 2005 10:20:07 +0100 Subject: [ARM] 2964/1: S3C2410 - serial: add .owner to driver Patch from Ben Dooks Initialise the driver's .owner field so that the device driver can be referenced to the module that owns it Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 50d7870..eff2158 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1235,6 +1235,7 @@ static int s3c2400_serial_probe(struct device *dev) static struct device_driver s3c2400_serial_drv = { .name = "s3c2400-uart", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2400_serial_probe, .remove = s3c24xx_serial_remove, @@ -1338,6 +1339,7 @@ static int s3c2410_serial_probe(struct device *dev) static struct device_driver s3c2410_serial_drv = { .name = "s3c2410-uart", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2410_serial_probe, .remove = s3c24xx_serial_remove, @@ -1499,6 +1501,7 @@ static int s3c2440_serial_probe(struct device *dev) static struct device_driver s3c2440_serial_drv = { .name = "s3c2440-uart", + .owner = THIS_MODULE, .bus = &platform_bus_type, .probe = s3c2440_serial_probe, .remove = s3c24xx_serial_remove, -- cgit v0.10.2 From 220ec0291130a932b32b2c66a10e9c5019dab702 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 10 Oct 2005 11:13:17 -0400 Subject: [PATCH] pcmcia: fix task state at pccard thread exit The pccardd thread has a race in it that it can shutdown in the TASK_INTERRUPTIBLE state. Make sure we mark ourselves runnable again as we remove ourselves from the wait queue. Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index fabd352..d5e7642 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -689,6 +689,9 @@ static int pccardd(void *__skt) schedule(); try_to_freeze(); } + /* make sure we are running before we exit */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&skt->thread_wait, &wait); /* remove from the device core */ -- cgit v0.10.2 From 5cd10daa0c7fc1410e1c0d685cbc9622c769eb16 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:05 +0200 Subject: [PATCH] Uml: hide commands when not being verbose Add a missing $(Q) to a "ln" invocation. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/Makefile b/arch/um/Makefile index 7af37e3..e1ffad2 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -152,7 +152,7 @@ archclean: $(SYMLINK_HEADERS): @echo ' SYMLINK $@' ifneq ($(KBUILD_SRC),) - ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@ + $(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@ else $(Q)cd $(TOPDIR)/$(dir $@) ; \ ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@) -- cgit v0.10.2 From 9e3d862e5c341c59b673c9cadd64210ca03cb41e Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:18 +0200 Subject: [PATCH] uml: add mode=skas0 as a synonym of skas0 Too many people were confused by skas0 and tried using "mode=skas0". And after all, they are right - accept this. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 6af8317..b99ab41 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -143,11 +143,22 @@ static int __init skas0_cmd_param(char *str, int* add) return 0; } +/* The two __uml_setup would conflict, without this stupid alias. */ + +static int __init mode_skas0_cmd_param(char *str, int* add) + __attribute__((alias("skas0_cmd_param"))); + __uml_setup("skas0", skas0_cmd_param, "skas0\n" " Disables SKAS3 usage, so that SKAS0 is used, unless \n" " you specify mode=tt.\n\n"); +__uml_setup("mode=skas0", mode_skas0_cmd_param, + "mode=skas0\n" + " Disables SKAS3 usage, so that SKAS0 is used, unless you \n" + " specify mode=tt. Note that this was recently added - on \n" + " older kernels you must use simply \"skas0\".\n\n"); + static int force_sysemu_disabled = 0; static int __init nosysemu_cmd_param(char *str, int* add) -- cgit v0.10.2 From 54a8a2220c936a47840c9a3d74910c5a56fae2ed Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:26 +0200 Subject: [PATCH] uml: allow building .s/.i/.lst files from userspace files For files which need to include glibc headers (i.e. userspace files), we specified the correct flags only for .o, not for .s/.lst/.i. Fix this. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 59a1291..651d9d8 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -7,8 +7,8 @@ USER_SINGLE_OBJS := \ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \ - $(CFLAGS_$(notdir $@)) +$(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \ + c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) $(USER_OBJS): cmd_checksrc = $(USER_OBJS): quiet_cmd_checksrc = $(USER_OBJS): cmd_force_checksrc = -- cgit v0.10.2 From 855ec613ca7e1953d96d7ea81af90392678788f5 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:35 +0200 Subject: [PATCH] uml: restore include breakage, breaking binary format of COW driver Commit 44456d37b59d8e541936ed26d8b6e08d27e88ac1, between 2.6.13-rc3 and -rc4, was a "nice cleanup" which broke something. Revert the offending part. It broke because: a) because this part doesn't fall under the description b) the author didn't know what he was doing here c) the author didn't try to compile the existing code and see that it worked perfectly. d) the author didn't ask us what was happening e) you didn't either, and somebody there should have learned that UML is a bit different. In fact, UML is special in linking to host libc and using its includes. In particular, since host includes always define both __BIG_ENDIAN and __LITTLE_ENDIAN, ntohll() macros started thinking to be in a big-endian world; and on-disk compatibility was broken. Many thanks go to Nix for reporting the problem and correctly diagnosing an endianness problem. Btw, this patch restores the previous code, which worked; but the definitions would be uncorrect if used in kernelspace files. Next patch addresses that. Cc: Nix , Olaf Hering Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 4fcf3a8..4fcbe8b 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -3,10 +3,10 @@ #include -#if defined(__BIG_ENDIAN) +#if __BYTE_ORDER == __BIG_ENDIAN # define ntohll(x) (x) # define htonll(x) (x) -#elif defined(__LITTLE_ENDIAN) +#elif __BYTE_ORDER == __LITTLE_ENDIAN # define ntohll(x) bswap_64(x) # define htonll(x) bswap_64(x) #else -- cgit v0.10.2 From 028c0cc16e429ae24d9b8aacc64f4438bdfac0cc Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:45 +0200 Subject: [PATCH] uml: cleanup byte order macros for COW driver After restoring the existing code, make it work also when included in kernelspace code (which isn't currently the case, but at least this will prevent people from "fixing" it as just happened). Whitespace is fixed in next patch - it cluttered the diff too much. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 4fcbe8b..c54e20a 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -3,6 +3,26 @@ #include +#if defined(__KERNEL__) + +# include + +# if defined(__BIG_ENDIAN) +# define ntohll(x) (x) +# define htonll(x) (x) +# elif defined(__LITTLE_ENDIAN) +# define ntohll(x) be64_to_cpu(x) +# define htonll(x) cpu_to_be64(x) +# else +# error "Could not determine byte order" +# endif + +#else +/* For the definition of ntohl, htonl and __BYTE_ORDER */ +#include +#include +#if defined(__BYTE_ORDER) + #if __BYTE_ORDER == __BIG_ENDIAN # define ntohll(x) (x) # define htonll(x) (x) @@ -10,8 +30,13 @@ # define ntohll(x) bswap_64(x) # define htonll(x) bswap_64(x) #else -#error "__BYTE_ORDER not defined" +# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" +#endif + +#else /* ! defined(__BYTE_ORDER) */ +# error "Could not determine byte order: __BYTE_ORDER not defined" #endif +#endif /* ! defined(__KERNEL__) */ extern int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, int alignment, int *bitmap_offset_out, diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index a8ce6fc..fbe2217 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -9,7 +9,6 @@ #include #include #include -#include #include "os.h" -- cgit v0.10.2 From 52a2d3e45e06012a662f627177729d3196ba8903 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 9 Oct 2005 21:37:53 +0200 Subject: [PATCH] uml: cleanup whitespace for COW driver Fix whitespace - I split this off the previous patch for easier review. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index c54e20a..dc36b22 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -23,15 +23,15 @@ #include #if defined(__BYTE_ORDER) -#if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(x) (x) -# define htonll(x) (x) -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define ntohll(x) bswap_64(x) -# define htonll(x) bswap_64(x) -#else -# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" -#endif +# if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(x) (x) +# define htonll(x) (x) +# elif __BYTE_ORDER == __LITTLE_ENDIAN +# define ntohll(x) bswap_64(x) +# define htonll(x) bswap_64(x) +# else +# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" +# endif #else /* ! defined(__BYTE_ORDER) */ # error "Could not determine byte order: __BYTE_ORDER not defined" -- cgit v0.10.2 From 3dd083255ddcfa87751fa8e32f61a9547a15a541 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 9 Oct 2005 21:19:40 +0200 Subject: [PATCH] x86_64: Set up safe page tables during resume The following patch makes swsusp avoid the possible temporary corruption of page translation tables during resume on x86-64. This is achieved by creating a copy of the relevant page tables that will not be modified by swsusp and can be safely used by it on resume. The problem is that during resume on x86-64 swsusp may temporarily corrupt the page tables used for the direct mapping of RAM. If that happens, a page fault occurs and cannot be handled properly, which leads to the solid hang of the affected system. This leads to the loss of the system's state from before suspend and may result in the loss of data or the corruption of filesystems, so it is a serious issue. Also, it appears to happen quite often (for me, as often as 50% of the time). The problem is related to the fact that (at least) one of the PMD entries used in the direct memory mapping (starting at PAGE_OFFSET) points to a page table the physical address of which is much greater than the physical address of the PMD entry itself. Moreover, unfortunately, the physical address of the page table before suspend (i.e. the one stored in the suspend image) happens to be different to the physical address of the corresponding page table used during resume (i.e. the one that is valid right before swsusp_arch_resume() in arch/x86_64/kernel/suspend_asm.S is executed). Thus while the image is restored, the "offending" PMD entry gets overwritten, so it does not point to the right physical address any more (i.e. there's no page table at the address pointed to by it, because it points to the address the page table has been at during suspend). Consequently, if the PMD entry is used later on, and it _is_ used in the process of copying the image pages, a page fault occurs, but it cannot be handled in the normal way and the system hangs. In principle we can call create_resume_mapping() from swsusp_arch_resume() (ie. from suspend_asm.S), but then the memory allocations in create_resume_mapping(), resume_pud_mapping(), and resume_pmd_mapping() must be made carefully so that we use _only_ NosaveFree pages in them (the other pages are overwritten by the loop in swsusp_arch_resume()). Additionally, we are in atomic context at that time, so we cannot use GFP_KERNEL. Moreover, if one of the allocations fails, we should free all of the allocated pages, so we need to trace them somehow. All of this is done in the appended patch, except that the functions populating the page tables are located in arch/x86_64/kernel/suspend.c rather than in init.c. It may be done in a more elegan way in the future, with the help of some swsusp patches that are in the works now. [AK: move some externs into headers, renamed a function] Signed-off-by: Rafael J. Wysocki Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index ebb9abf..f066c6a 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include struct saved_context saved_context; @@ -140,4 +142,129 @@ void fix_processor_context(void) } +#ifdef CONFIG_SOFTWARE_SUSPEND +/* Defined in arch/x86_64/kernel/suspend_asm.S */ +extern int restore_image(void); +pgd_t *temp_level4_pgt; + +static void **pages; + +static inline void *__add_page(void) +{ + void **c; + + c = (void **)get_usable_page(GFP_ATOMIC); + if (c) { + *c = pages; + pages = c; + } + return c; +} + +static inline void *__next_page(void) +{ + void **c; + + c = pages; + if (c) { + pages = *c; + *c = NULL; + } + return c; +} + +/* + * Try to allocate as many usable pages as needed and daisy chain them. + * If one allocation fails, free the pages allocated so far + */ +static int alloc_usable_pages(unsigned long n) +{ + void *p; + + pages = NULL; + do + if (!__add_page()) + break; + while (--n); + if (n) { + p = __next_page(); + while (p) { + free_page((unsigned long)p); + p = __next_page(); + } + return -ENOMEM; + } + return 0; +} + +static void res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) +{ + long i, j; + + i = pud_index(address); + pud = pud + i; + for (; i < PTRS_PER_PUD; pud++, i++) { + unsigned long paddr; + pmd_t *pmd; + + paddr = address + i*PUD_SIZE; + if (paddr >= end) + break; + + pmd = (pmd_t *)__next_page(); + set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE)); + for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { + unsigned long pe; + + if (paddr >= end) + break; + pe = _PAGE_NX | _PAGE_PSE | _KERNPG_TABLE | paddr; + pe &= __supported_pte_mask; + set_pmd(pmd, __pmd(pe)); + } + } +} + +static void set_up_temporary_mappings(void) +{ + unsigned long start, end, next; + + temp_level4_pgt = (pgd_t *)__next_page(); + + /* It is safe to reuse the original kernel mapping */ + set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map), + init_level4_pgt[pgd_index(__START_KERNEL_map)]); + + /* Set up the direct mapping from scratch */ + start = (unsigned long)pfn_to_kaddr(0); + end = (unsigned long)pfn_to_kaddr(end_pfn); + + for (; start < end; start = next) { + pud_t *pud = (pud_t *)__next_page(); + next = start + PGDIR_SIZE; + if (next > end) + next = end; + res_phys_pud_init(pud, __pa(start), __pa(next)); + set_pgd(temp_level4_pgt + pgd_index(start), + mk_kernel_pgd(__pa(pud))); + } +} + +int swsusp_arch_resume(void) +{ + unsigned long n; + + n = ((end_pfn << PAGE_SHIFT) + PUD_SIZE - 1) >> PUD_SHIFT; + n += (n + PTRS_PER_PUD - 1) / PTRS_PER_PUD + 1; + pr_debug("swsusp_arch_resume(): pages needed = %lu\n", n); + if (alloc_usable_pages(n)) { + free_eaten_memory(); + return -ENOMEM; + } + /* We have got enough memory and from now on we cannot recover */ + set_up_temporary_mappings(); + restore_image(); + return 0; +} +#endif /* CONFIG_SOFTWARE_SUSPEND */ diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S index 4d659e9..320b6fb 100644 --- a/arch/x86_64/kernel/suspend_asm.S +++ b/arch/x86_64/kernel/suspend_asm.S @@ -39,12 +39,13 @@ ENTRY(swsusp_arch_suspend) call swsusp_save ret -ENTRY(swsusp_arch_resume) - /* set up cr3 */ - leaq init_level4_pgt(%rip),%rax - subq $__START_KERNEL_map,%rax - movq %rax,%cr3 - +ENTRY(restore_image) + /* switch to temporary page tables */ + movq $__PAGE_OFFSET, %rdx + movq temp_level4_pgt(%rip), %rax + subq %rdx, %rax + movq %rax, %cr3 + /* Flush TLB */ movq mmu_cr4_features(%rip), %rax movq %rax, %rdx andq $~(1<<7), %rdx # PGE @@ -69,6 +70,10 @@ loop: movq pbe_next(%rdx), %rdx jmp loop done: + /* go back to the original page tables */ + leaq init_level4_pgt(%rip), %rax + subq $__START_KERNEL_map, %rax + movq %rax, %cr3 /* Flush TLB, including "global" things (vmalloc) */ movq mmu_cr4_features(%rip), %rax movq %rax, %rdx diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f2e96fd..ad15a54 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -71,5 +71,7 @@ void restore_processor_state(void); struct saved_context; void __save_processor_state(struct saved_context *ctxt); void __restore_processor_state(struct saved_context *ctxt); +extern unsigned long get_usable_page(unsigned gfp_mask); +extern void free_eaten_memory(void); #endif /* _LINUX_SWSUSP_H */ diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index acf79ac..2d5c456 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -1095,7 +1095,7 @@ static inline void eat_page(void *page) *eaten_memory = c; } -static unsigned long get_usable_page(unsigned gfp_mask) +unsigned long get_usable_page(unsigned gfp_mask) { unsigned long m; @@ -1109,7 +1109,7 @@ static unsigned long get_usable_page(unsigned gfp_mask) return m; } -static void free_eaten_memory(void) +void free_eaten_memory(void) { unsigned long m; void **c; @@ -1481,11 +1481,12 @@ static int read_suspend_image(void) /* Allocate memory for the image and read the data from swap */ error = check_pagedir(pagedir_nosave); - free_eaten_memory(); + if (!error) error = data_read(pagedir_nosave); if (error) { /* We fail cleanly */ + free_eaten_memory(); for_each_pbe (p, pagedir_nosave) if (p->address) { free_page(p->address); -- cgit v0.10.2 From 50f72b57946d565db74fae71bac23f3f319311c8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Sun, 9 Oct 2005 16:11:44 -0400 Subject: [PATCH] uml: fix x86_64 with !CONFIG_FRAME_POINTER UML/x86_64 doesn't run when built with frame pointers disabled. There was an implicit frame pointer assumption in the stub segfault handler. With frame pointers disabled, UML dies on handling its first page fault. The container-of part of this is from Paolo Giarrusso . Signed-off-by: Jeff Dike Signed-off-by: Linus Torvalds diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index 65a131b..d1e53bd 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -10,6 +10,22 @@ #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" +#include + +/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition + * in the libc headers anywhere. + */ +struct rt_sigframe +{ + char *pretcode; + struct ucontext uc; + struct siginfo info; +}; + +/* Copied here from - we're userspace. */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) @@ -17,16 +33,19 @@ stub_segv_handler(int sig) struct ucontext *uc; __asm__("movq %%rdx, %0" : "=g" (uc) :); - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), - &uc->uc_mcontext); + GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), + &uc->uc_mcontext); - __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); + __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" - "syscall": : "g" (__NR_kill), "g" (SIGUSR1)); - /* Two popqs to restore the stack to the state just before entering - * the handler, one pops the return address, the other pops the frame - * pointer. + "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : + "%rdi", "%rax", "%rsi"); + /* sys_sigreturn expects that the stack pointer will be 8 bytes into + * the signal frame. So, we use the ucontext pointer, which we know + * already, to get the signal frame pointer, and add 8 to that. */ - __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g" - (__NR_rt_sigreturn)); + __asm__("movq %0, %%rsp": : + "g" ((unsigned long) container_of(uc, struct rt_sigframe, + uc) + 8)); + __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); } -- cgit v0.10.2 From 1cc956e12aedfdc6baf6312bc36a6b5a71af3c9d Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 Oct 2005 10:41:32 -0500 Subject: [PATCH] relayfs: fix bogus param value in call to vmap The third param in this call to vmap shouldn't be GFP_KERNEL, which makes no sense, but rather VM_MAP. Thanks to Al Viro for spotting this. Signed-off-by: Tom Zanussi Signed-off-by: Linus Torvalds diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c index 2aa8e27..84e21ff 100644 --- a/fs/relayfs/buffers.c +++ b/fs/relayfs/buffers.c @@ -109,7 +109,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size) if (unlikely(!buf->page_array[i])) goto depopulate; } - mem = vmap(buf->page_array, n_pages, GFP_KERNEL, PAGE_KERNEL); + mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); if (!mem) goto depopulate; -- cgit v0.10.2 From 867f8b4e47a17c5d68c98dc6eee12739c4490056 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 9 Oct 2005 10:37:47 +1000 Subject: [PATCH] ide: Workaround PM problem The logic in ide_do_request() doesn't guarantee that both drives will be serviced after a call. It may "forget" to service one in some circumstances, including when one of the drive is suspended (it will eventually fail to service the slave when the master is suspended for example). This prevents the wakeup requests that gets queued on wakeup from sleep from beeing serviced in some cases when 2 drives are sharing an IDE bus. The problem is deep enough in the way this code works (and there are probably a few other problematic but rare corner cases) and fixing it would require some major rethinking of the way IDE decides which channel to service. This is not 2.6.14 material. However, in the meantime, Bart has accepted this simple workaround that will fix the crash on wakeup from sleep since this specific corner case is actually hitting users to get into 2.6.14. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9e9cf14..5275cbb 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1101,6 +1101,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) ide_hwif_t *hwif; struct request *rq; ide_startstop_t startstop; + int loops = 0; /* for atari only: POSSIBLY BROKEN HERE(?) */ ide_get_lock(ide_intr, hwgroup); @@ -1153,6 +1154,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) /* no more work for this hwgroup (for now) */ return; } + again: hwif = HWIF(drive); if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && @@ -1192,8 +1194,14 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) * though. I hope that doesn't happen too much, hopefully not * unless the subdriver triggers such a thing in its own PM * state machine. + * + * We count how many times we loop here to make sure we service + * all drives in the hwgroup without looping for ever */ if (drive->blocked && !blk_pm_request(rq) && !(rq->flags & REQ_PREEMPT)) { + drive = drive->next ? drive->next : hwgroup->drive; + if (loops++ < 4 && !blk_queue_plugged(drive->queue)) + goto again; /* We clear busy, there should be no pending ATA command at this point. */ hwgroup->busy = 0; break; -- cgit v0.10.2 From d347f372273c2b3d86a66e2e1c94c790c208e166 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 9 Oct 2005 18:54:23 +0200 Subject: [PATCH] i386: fix stack alignment for signal handlers This fixes the setup of the alignment of the signal frame, so that all signal handlers are run with a properly aligned stack frame. The current code "over-aligns" the stack pointer so that the stack frame is effectively always mis-aligned by 4 bytes. But what we really want is that on function entry ((sp + 4) & 15) == 0, which matches what would happen if the stack were aligned before a "call" instruction. Signed-off-by: Markus F.X.J. Oberhumer Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 61eb0c8..adcd069 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -338,7 +338,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) esp = (unsigned long) ka->sa.sa_restorer; } - return (void __user *)((esp - frame_size) & -8ul); + esp -= frame_size; + /* Align the stack pointer according to the i386 ABI, + * i.e. so that on function entry ((sp + 4) & 15) == 0. */ + esp = ((esp + 4) & -16ul) - 4; + return (void __user *) esp; } /* These symbols are defined with the addresses in the vsyscall page. diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 66e2821..0903cc1 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -425,7 +425,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) rsp = (unsigned long) ka->sa.sa_restorer; } - return (void __user *)((rsp - frame_size) & -8UL); + rsp -= frame_size; + /* Align the stack pointer according to the i386 ABI, + * i.e. so that on function entry ((sp + 4) & 15) == 0. */ + rsp = ((rsp + 4) & -16ul) - 4; + return (void __user *) rsp; } int ia32_setup_frame(int sig, struct k_sigaction *ka, -- cgit v0.10.2 From 585f54575d832506bbe9b5a2f435f37b81efc849 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 10 Oct 2005 18:22:17 +0100 Subject: [ARM] 2956/1: fix the "Fix gcc4 build errors in ucb1x00-core.c" Patch from Nicolas Pitre drivers/mfd/ucb1x00-core.c: In function 'ucb1x00_probe': drivers/mfd/ucb1x00-core.c:482: error: 'ucb1x00_class' undeclared (first use in this function) Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 612564a..e335d54 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -457,6 +457,17 @@ static int ucb1x00_detect_irq(struct ucb1x00 *ucb) return probe_irq_off(mask); } +static void ucb1x00_release(struct class_device *dev) +{ + struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); + kfree(ucb); +} + +static struct class ucb1x00_class = { + .name = "ucb1x00", + .release = ucb1x00_release, +}; + static int ucb1x00_probe(struct mcp *mcp) { struct ucb1x00 *ucb; @@ -546,17 +557,6 @@ static void ucb1x00_remove(struct mcp *mcp) class_device_unregister(&ucb->cdev); } -static void ucb1x00_release(struct class_device *dev) -{ - struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); - kfree(ucb); -} - -static struct class ucb1x00_class = { - .name = "ucb1x00", - .release = ucb1x00_release, -}; - int ucb1x00_register_driver(struct ucb1x00_driver *drv) { struct ucb1x00 *ucb; -- cgit v0.10.2 From 86b324874f571297237c0c940bfe7e5f0f9ca5d2 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 10 Oct 2005 18:24:06 +0100 Subject: [ARM] 2965/1: defconfig for the ARM Spitz platform Patch from Vincent Sanders Add a defconfig for the ARM Spitz Zarus platform Signed-off-by: Richard Purdie Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig new file mode 100644 index 0000000..900e04f --- /dev/null +++ b/arch/arm/configs/spitz_defconfig @@ -0,0 +1,1401 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14-rc3 +# Sun Oct 9 17:11:19 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_PXA_SHARPSL=y +# CONFIG_PXA_SHARPSL_25x is not set +CONFIG_PXA_SHARPSL_27x=y +CONFIG_MACH_SPITZ=y +CONFIG_MACH_BORZOI=y +CONFIG_PXA27x=y +CONFIG_PXA_SHARP_Cxx00=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y +CONFIG_SHARP_PARAM=y +CONFIG_SHARP_SCOOP=y + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_PCMCIA_PXA2XX=y + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +# CONFIG_IP_NF_MATCH_STRING is not set +CONFIG_IP_NF_FILTER=m +# CONFIG_IP_NF_TARGET_REJECT is not set +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +# CONFIG_IP_NF_TARGET_NFQUEUE is not set +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +# CONFIG_IP_NF_TARGET_MASQUERADE is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_TOS is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +# CONFIG_IP_NF_TARGET_MARK is not set +# CONFIG_IP_NF_TARGET_CLASSIFY is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_TARGET_NOTRACK is not set +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +# CONFIG_IP6_NF_TARGET_LOG is not set +# CONFIG_IP6_NF_TARGET_REJECT is not set +# CONFIG_IP6_NF_TARGET_NFQUEUE is not set +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_MARK is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_RAW=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set + +# +# Dongle support +# + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_SIGMATEL_FIR is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VIA_FIR is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +# CONFIG_BT_HCIUSB_SCO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_BCSP_TXCRC=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +# CONFIG_IEEE80211_CRYPT_CCMP is not set +# CONFIG_IEEE80211_CRYPT_TKIP is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_SHARP_SL=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_H1900 is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_SHARPSL=y +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_HERMES=m +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_CS=m +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_CORGI is not set +CONFIG_KEYBOARD_SPITZ=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_CORGI=y +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_PXA=y +# CONFIG_FB_W100 is not set +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_DEVICE=y +CONFIG_BACKLIGHT_CORGI=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# + +# +# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +# CONFIG_USB_ACECAD is not set +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_MTOUCH=m +# CONFIG_USB_ITMTOUCH is not set +CONFIG_USB_EGALAX=m +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Multimedia devices +# +CONFIG_USB_DABUSB=m + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +CONFIG_USB_SERIAL_BELKIN=m +# CONFIG_USB_SERIAL_WHITEHEAT is not set +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +# CONFIG_USB_SERIAL_CP2101 is not set +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +# CONFIG_USB_SERIAL_OPTION is not set +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_DUMMY_HCD=y +CONFIG_USB_DUMMY_HCD=m +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_PXA=y +# CONFIG_MMC_WBSD is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_TEST=m + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v0.10.2 From b0bdc7be78931dfbfaec8bd0da44a5f4e158ca8f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 10 Oct 2005 18:24:07 +0100 Subject: [ARM] 2966/1: defconfig for the ARM Poodle platform Patch from Vincent Sanders Add a defconfig for the ARM Poodle Zarus platform Signed-off-by: Richard Purdie Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/configs/poodle_defconfig b/arch/arm/configs/poodle_defconfig new file mode 100644 index 0000000..7282290 --- /dev/null +++ b/arch/arm/configs/poodle_defconfig @@ -0,0 +1,1015 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14-rc3 +# Sun Oct 9 17:04:29 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_PXA_SHARPSL=y +CONFIG_PXA_SHARPSL_25x=y +# CONFIG_PXA_SHARPSL_27x is not set +CONFIG_MACH_POODLE=y +# CONFIG_MACH_CORGI is not set +# CONFIG_MACH_SHEPHERD is not set +# CONFIG_MACH_HUSKY is not set +CONFIG_PXA25x=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y +CONFIG_SHARP_LOCOMO=y +CONFIG_SHARP_PARAM=y +CONFIG_SHARP_SCOOP=y + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_PCMCIA_PXA2XX=y + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_SHARP_SL=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_H1900 is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_SHARPSL=y +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_TSDEV=y +CONFIG_INPUT_TSDEV_SCREEN_X=240 +CONFIG_INPUT_TSDEV_SCREEN_Y=320 +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_LOCOMO=y +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_CORGI is not set +CONFIG_KEYBOARD_SPITZ=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_PXA is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +CONFIG_I2C_DEBUG_CORE=y +CONFIG_I2C_DEBUG_ALGO=y +CONFIG_I2C_DEBUG_BUS=y +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# + +# +# Video Adapters +# +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_OVCAMCHIP is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_MAESTRO is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_PXA=y +# CONFIG_FB_W100 is not set +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB is not set + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_USB_GADGET_PXA2XX=y +CONFIG_USB_PXA2XX=y +# CONFIG_USB_PXA2XX_SMALL is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_PXA=y +# CONFIG_MMC_WBSD is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v0.10.2 From 36e5ea67590707a069ce3bcc179b38cdabebcfdd Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 10 Oct 2005 18:24:08 +0100 Subject: [ARM] 2967/1: defconfig for the ARM Corgi platform Patch from Vincent Sanders Add a defconfig for the ARM Corgi Zarus platform Signed-off-by: Richard Purdie Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig new file mode 100644 index 0000000..24987c8 --- /dev/null +++ b/arch/arm/configs/corgi_defconfig @@ -0,0 +1,1523 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14-rc3 +# Sun Oct 9 15:46:42 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +CONFIG_PXA_SHARPSL=y +CONFIG_PXA_SHARPSL_25x=y +# CONFIG_PXA_SHARPSL_27x is not set +# CONFIG_MACH_POODLE is not set +CONFIG_MACH_CORGI=y +CONFIG_MACH_SHEPHERD=y +CONFIG_MACH_HUSKY=y +CONFIG_PXA25x=y +CONFIG_PXA_SHARP_C7xx=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y +CONFIG_SHARP_PARAM=y +CONFIG_SHARP_SCOOP=y + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_PCMCIA_PXA2XX=y + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +# CONFIG_IP_NF_MATCH_STRING is not set +CONFIG_IP_NF_FILTER=m +# CONFIG_IP_NF_TARGET_REJECT is not set +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +# CONFIG_IP_NF_TARGET_NFQUEUE is not set +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +# CONFIG_IP_NF_TARGET_MASQUERADE is not set +# CONFIG_IP_NF_TARGET_REDIRECT is not set +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_TOS is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +# CONFIG_IP_NF_TARGET_MARK is not set +# CONFIG_IP_NF_TARGET_CLASSIFY is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_TARGET_NOTRACK is not set +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +# CONFIG_IP6_NF_TARGET_LOG is not set +# CONFIG_IP6_NF_TARGET_REJECT is not set +# CONFIG_IP6_NF_TARGET_NFQUEUE is not set +CONFIG_IP6_NF_MANGLE=m +# CONFIG_IP6_NF_TARGET_MARK is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_RAW=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set + +# +# Dongle support +# + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_SIGMATEL_FIR is not set +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VIA_FIR is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +# CONFIG_BT_HCIUSB_SCO is not set +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_BCSP_TXCRC=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +# CONFIG_IEEE80211_CRYPT_CCMP is not set +# CONFIG_IEEE80211_CRYPT_TKIP is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_SHARP_SL=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_H1900 is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_SHARPSL=y +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM_COUNT=16 +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_HERMES=m +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_CS=m +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_KEYBOARD_CORGI=y +CONFIG_KEYBOARD_SPITZ=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_CORGI=y +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_PXA=y +# CONFIG_I2C_PXA_SLAVE is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# + +# +# Video Adapters +# +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_OVCAMCHIP is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_MAESTRO is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_PXA is not set +CONFIG_FB_W100=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CORGI=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_OSS=y +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_ACI_MIXER is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_AWE32_SYNTH is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set +# CONFIG_SOUND_TVMIXER is not set +# CONFIG_SOUND_AD1980 is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set + +# +# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +# CONFIG_USB_ACECAD is not set +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_MTOUCH=m +# CONFIG_USB_ITMTOUCH is not set +CONFIG_USB_EGALAX=m +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Multimedia devices +# +CONFIG_USB_DABUSB=m +CONFIG_USB_VICAM=m +CONFIG_USB_DSBR=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +# CONFIG_USB_PWC is not set + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +CONFIG_USB_SERIAL_BELKIN=m +# CONFIG_USB_SERIAL_WHITEHEAT is not set +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +# CONFIG_USB_SERIAL_CP2101 is not set +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_USB_GADGET_PXA2XX=y +CONFIG_USB_PXA2XX=y +# CONFIG_USB_PXA2XX_SMALL is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_PXA=y +# CONFIG_MMC_WBSD is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_JFFS2_RUBIN=y +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_TEST=m + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v0.10.2 From 71e2b2ecc1c44cb4f2f3e68827af8b90246becac Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 10 Oct 2005 18:24:09 +0100 Subject: [ARM] 2968/1: defconfig for the ARM Collie platform Patch from Vincent Sanders Add a defconfig for the ARM Collie platform Signed-off-by: Richard Purdie Signed-off-by: Vincent Sanders Signed-off-by: Russell King diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig new file mode 100644 index 0000000..40dfe07 --- /dev/null +++ b/arch/arm/configs/collie_defconfig @@ -0,0 +1,888 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.14-rc3 +# Sun Oct 9 16:55:14 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_CAMELOT is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +CONFIG_ARCH_SA1100=y +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_SA1100_CERF is not set +CONFIG_SA1100_COLLIE=y +# CONFIG_SA1100_H3100 is not set +# CONFIG_SA1100_H3600 is not set +# CONFIG_SA1100_H3800 is not set +# CONFIG_SA1100_BADGE4 is not set +# CONFIG_SA1100_JORNADA720 is not set +# CONFIG_SA1100_HACKKIT is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_SHANNON is not set +# CONFIG_SA1100_SIMPAD is not set +# CONFIG_SA1100_SSP is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_SA1100=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4=y +CONFIG_CPU_CACHE_V4WB=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WB=y + +# +# Processor Features +# +CONFIG_SHARP_LOCOMO=y +CONFIG_SHARP_PARAM=y +CONFIG_SHARP_SCOOP=y + +# +# Bus support +# +CONFIG_ISA=y +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_SMP is not set +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_DISCONTIGMEM_MANUAL=y +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_DISCONTIGMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_NEED_MULTIPLE_NODES=y +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2 debug" +# CONFIG_XIP_KERNEL is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_DEBUG_DRIVER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +CONFIG_MTD_OBSOLETE_CHIPS=y +# CONFIG_MTD_AMDSTD is not set +CONFIG_MTD_SHARP=y +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_TSDEV=y +CONFIG_INPUT_TSDEV_SCREEN_X=240 +CONFIG_INPUT_TSDEV_SCREEN_Y=320 +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_LOCOMO=y +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# + +# +# I2C support +# +CONFIG_I2C=m +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ELEKTOR is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# +# CONFIG_MCP_SA11X0 is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# + +# +# Video Adapters +# +# CONFIG_VIDEO_PMS is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_OVCAMCHIP is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_MAESTRO is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SOFT_CURSOR=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_SA1100=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB is not set + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y -- cgit v0.10.2 From 094804c5a132f04c12dd4902ee15c64362e5c1af Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Oct 2005 01:03:39 +0200 Subject: [PATCH] x86_64: Fix change_page_attr cache flushing Noticed by Terence Ripperda Undo wrong change in global_flush_tlb. We need to flush the caches in all cases, not just when pages were reverted. This was a bogus optimization added earlier, but it was wrong. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 94862e1..b90e8fe 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c @@ -220,8 +220,6 @@ void global_flush_tlb(void) down_read(&init_mm.mmap_sem); df = xchg(&df_list, NULL); up_read(&init_mm.mmap_sem); - if (!df) - return; flush_map((df && !df->next) ? df->address : 0); for (; df; df = next_df) { next_df = df->next; -- cgit v0.10.2 From 5d8e1b181c4ad63e6ca90d51287b31afd400d2eb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 10 Oct 2005 16:12:13 -0700 Subject: [SPARC64]: Fix Ultra5, Ultra60, et al. boot failures. On the boot processor, we need to do the move onto the Linux trap table a little bit differently else we'll take unhandlable faults in the firmware address space. Previously we would do the following: 1) Disable PSTATE_IE in %pstate. 2) Set %tba by hand to sparc64_ttable_tl0 3) Initialize alternate, mmu, and interrupt global trap registers. 4) Call prom_set_traptable() That doesn't work very well actually with the way we boot the kernel VM these days. It worked by luck on many systems because the firmware accesses for the prom_set_traptable() call happened to be loaded into the TLB already, something we cannot assume. So the new scheme is this: 1) Clear PSTATE_IE in %pstate and set %pil to 15 2) Call prom_set_traptable() 3) Initialize alternate, mmu, and interrupt global trap registers. and this works quite well. This sequence has been moved into a callable function in assembler named setup-trap_table(). The idea is that eventually trampoline.S can use this code as well. That isn't possible currently due to some complications, but eventually we should be able to do it. Thanks to Meelis Roos for the Ultra5 boot failure report. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 2434049..f1dcdf8 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -382,32 +382,79 @@ tlb_fixup_done: nop /* Not reached... */ -/* IMPORTANT NOTE: Whenever making changes here, check - * trampoline.S as well. -jj */ - .globl setup_tba -setup_tba: /* i0 = is_starfire */ - save %sp, -160, %sp + /* This is meant to allow the sharing of this code between + * boot processor invocation (via setup_tba() below) and + * secondary processor startup (via trampoline.S). The + * former does use this code, the latter does not yet due + * to some complexities. That should be fixed up at some + * point. + */ + .globl setup_trap_table +setup_trap_table: + save %sp, -192, %sp + + /* Force interrupts to be disabled. Transferring over to + * the Linux trap table is a very delicate operation. + * Until we are actually on the Linux trap table, we cannot + * get the PAGE_OFFSET linear mappings translated. We need + * that mapping to be setup in order to initialize the firmware + * page tables. + * + * So there is this window of time, from the return from + * prom_set_trap_table() until inherit_prom_mappings_post() + * (in arch/sparc64/mm/init.c) completes, during which no + * firmware address space accesses can be made. + */ + rdpr %pstate, %o1 + andn %o1, PSTATE_IE, %o1 + wrpr %o1, 0x0, %pstate + wrpr %g0, 15, %pil - rdpr %tba, %g7 - sethi %hi(prom_tba), %o1 - or %o1, %lo(prom_tba), %o1 - stx %g7, [%o1] + /* Ok, now make the final valid firmware call to jump over + * to the Linux trap table. + */ + call prom_set_trap_table + sethi %hi(sparc64_ttable_tl0), %o0 + + /* Start using proper page size encodings in ctx register. */ + sethi %hi(sparc64_kern_pri_context), %g3 + ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 + mov PRIMARY_CONTEXT, %g1 + stxa %g2, [%g1] ASI_DMMU + membar #Sync + + /* The Linux trap handlers expect various trap global registers + * to be setup with some fixed values. So here we set these + * up very carefully. These globals are: + * + * Alternate Globals (PSTATE_AG): + * + * %g6 --> current_thread_info() + * + * MMU Globals (PSTATE_MG): + * + * %g1 --> TLB_SFSR + * %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB | + * _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) + * ^ 0xfffff80000000000) + * (this %g2 value is used for computing the PAGE_OFFSET kernel + * TLB entries quickly, the virtual address of the fault XOR'd + * with this %g2 value is the PTE to load into the TLB) + * %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE + * + * Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()): + * + * %g6 --> __irq_work[smp_processor_id()] + */ - /* Setup "Linux" globals 8-) */ rdpr %pstate, %o1 mov %g6, %o2 - wrpr %o1, (PSTATE_AG|PSTATE_IE), %pstate - sethi %hi(sparc64_ttable_tl0), %g1 - wrpr %g1, %tba + wrpr %o1, PSTATE_AG, %pstate mov %o2, %g6 - /* Set up MMU globals */ - wrpr %o1, (PSTATE_MG|PSTATE_IE), %pstate - - /* Set fixed globals used by dTLB miss handler. */ #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000) #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W) - + wrpr %o1, PSTATE_MG, %pstate mov TSB_REG, %g1 stxa %g0, [%g1] ASI_DMMU membar #Sync @@ -419,17 +466,17 @@ setup_tba: /* i0 = is_starfire */ sllx %g2, 32, %g2 or %g2, KERN_LOWBITS, %g2 - BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base) - ba,pt %xcc, spitfire_vpte_base + BRANCH_IF_ANY_CHEETAH(g3,g7,8f) + ba,pt %xcc, 9f nop -cheetah_vpte_base: +8: sethi %uhi(VPTE_BASE_CHEETAH), %g3 or %g3, %ulo(VPTE_BASE_CHEETAH), %g3 ba,pt %xcc, 2f sllx %g3, 32, %g3 -spitfire_vpte_base: +9: sethi %uhi(VPTE_BASE_SPITFIRE), %g3 or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3 sllx %g3, 32, %g3 @@ -455,29 +502,37 @@ spitfire_vpte_base: sllx %o2, 32, %o2 wr %o2, %asr25 - /* Ok, we're done setting up all the state our trap mechanims needs, - * now get back into normal globals and let the PROM know what is up. - */ 2: wrpr %g0, %g0, %wstate - wrpr %o1, PSTATE_IE, %pstate + wrpr %o1, 0x0, %pstate call init_irqwork_curcpu nop - call prom_set_trap_table - sethi %hi(sparc64_ttable_tl0), %o0 - - /* Start using proper page size encodings in ctx register. */ - sethi %hi(sparc64_kern_pri_context), %g3 - ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2 - mov PRIMARY_CONTEXT, %g1 - stxa %g2, [%g1] ASI_DMMU - membar #Sync - + /* Now we can turn interrupts back on. */ rdpr %pstate, %o1 or %o1, PSTATE_IE, %o1 wrpr %o1, 0, %pstate + wrpr %g0, 0x0, %pil + + ret + restore + + .globl setup_tba +setup_tba: /* i0 = is_starfire */ + save %sp, -192, %sp + + /* The boot processor is the only cpu which invokes this + * routine, the other cpus set things up via trampoline.S. + * So save the OBP trap table address here. + */ + rdpr %tba, %g7 + sethi %hi(prom_tba), %o1 + or %o1, %lo(prom_tba), %o1 + stx %g7, [%o1] + + call setup_trap_table + nop ret restore -- cgit v0.10.2 From 46113830a18847cff8da73005e57bc49c2f95a56 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 19:44:29 +0200 Subject: [PATCH] Fix signal sending in usbdevio on async URB completion If a process issues an URB from userspace and (starts to) terminate before the URB comes back, we run into the issue described above. This is because the urb saves a pointer to "current" when it is posted to the device, but there's no guarantee that this pointer is still valid afterwards. In fact, there are three separate issues: 1) the pointer to "current" can become invalid, since the task could be completely gone when the URB completion comes back from the device. 2) Even if the saved task pointer is still pointing to a valid task_struct, task_struct->sighand could have gone meanwhile. 3) Even if the process is perfectly fine, permissions may have changed, and we can no longer send it a signal. So what we do instead, is to save the PID and uid's of the process, and introduce a new kill_proc_info_as_uid() function. Signed-off-by: Harald Welte [ Fixed up types and added symbol exports ] Signed-off-by: Linus Torvalds diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index b4265aa..6c35dcb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -30,6 +30,8 @@ * Revision history * 22.12.1999 0.1 Initial release (split from proc_usb.c) * 04.01.2000 0.2 Turned into its own filesystem + * 30.09.2005 0.3 Fix user-triggerable oops in async URB delivery + * (CAN-2005-3055) */ /*****************************************************************************/ @@ -58,7 +60,8 @@ static struct class *usb_device_class; struct async { struct list_head asynclist; struct dev_state *ps; - struct task_struct *task; + pid_t pid; + uid_t uid, euid; unsigned int signr; unsigned int ifnum; void __user *userbuffer; @@ -290,7 +293,8 @@ static void async_completed(struct urb *urb, struct pt_regs *regs) sinfo.si_errno = as->urb->status; sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = as->userurb; - send_sig_info(as->signr, &sinfo, as->task); + kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid, + as->euid); } wake_up(&ps->wait); } @@ -988,7 +992,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->userbuffer = NULL; as->signr = uurb->signr; as->ifnum = ifnum; - as->task = current; + as->pid = current->pid; + as->uid = current->uid; + as->euid = current->euid; if (!(uurb->endpoint & USB_DIR_IN)) { if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) { free_async(as); diff --git a/include/linux/sched.h b/include/linux/sched.h index c3ba31f..27519df 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1018,6 +1018,7 @@ extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); extern int kill_pg_info(int, struct siginfo *, pid_t); extern int kill_proc_info(int, struct siginfo *, pid_t); +extern int kill_proc_info_as_uid(int, struct siginfo *, pid_t, uid_t, uid_t); extern void do_notify_parent(struct task_struct *, int); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); diff --git a/kernel/signal.c b/kernel/signal.c index cba193c..50c9926 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1193,6 +1193,40 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) return error; } +/* like kill_proc_info(), but doesn't use uid/euid of "current" */ +int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, + uid_t uid, uid_t euid) +{ + int ret = -EINVAL; + struct task_struct *p; + + if (!valid_signal(sig)) + return ret; + + read_lock(&tasklist_lock); + p = find_task_by_pid(pid); + if (!p) { + ret = -ESRCH; + goto out_unlock; + } + if ((!info || ((unsigned long)info != 1 && + (unsigned long)info != 2 && SI_FROMUSER(info))) + && (euid != p->suid) && (euid != p->uid) + && (uid != p->suid) && (uid != p->uid)) { + ret = -EPERM; + goto out_unlock; + } + if (sig && p->sighand) { + unsigned long flags; + spin_lock_irqsave(&p->sighand->siglock, flags); + ret = __group_send_sig_info(sig, info, p); + spin_unlock_irqrestore(&p->sighand->siglock, flags); + } +out_unlock: + read_unlock(&tasklist_lock); + return ret; +} +EXPORT_SYMBOL_GPL(kill_proc_info_as_uid); /* * kill_something_info() interprets pid in interesting ways just like kill(2). -- cgit v0.10.2 From d7dd8a72ab8d305fbe1c4bb571e0633eba3a8d23 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 10 Oct 2005 16:31:30 -0700 Subject: Use the new "kill_proc_info_as_uid()" for USB disconnect too All the same issues - we can't just save the pointer to the thread, we must save the pid/uid/euid combination. Signed-off-by: Linus Torvalds diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6c35dcb..487ff67 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -530,7 +530,9 @@ static int usbdev_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&ps->async_completed); init_waitqueue_head(&ps->wait); ps->discsignr = 0; - ps->disctask = current; + ps->disc_pid = current->pid; + ps->disc_uid = current->uid; + ps->disc_euid = current->euid; ps->disccontext = NULL; ps->ifclaimed = 0; wmb(); diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 640f41e..d07bba0 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -713,7 +713,7 @@ void usbfs_remove_device(struct usb_device *dev) sinfo.si_errno = EPIPE; sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = ds->disccontext; - send_sig_info(ds->discsignr, &sinfo, ds->disctask); + kill_proc_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid); } } usbfs_update_special(); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 83d48c8..e6504f3 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -52,7 +52,8 @@ struct dev_state { struct list_head async_completed; wait_queue_head_t wait; /* wake up if a request completed */ unsigned int discsignr; - struct task_struct *disctask; + pid_t disc_pid; + uid_t disc_uid, disc_euid; void __user *disccontext; unsigned long ifclaimed; }; -- cgit v0.10.2 From 421c7ce6d001fce28b1fa8fdd2e7ded0ed8a0ad5 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 10 Oct 2005 22:32:45 +0200 Subject: [PATCH] x86_64: Allocate cpu local data for all possible CPUs CPU hotplug fills up the possible map to NR_CPUs, but it did that after setting up per CPU data. This lead to CPU data not getting allocated for all possible CPUs, which lead to various side effects. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index bd33be2..7919089 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -87,6 +87,10 @@ void __init setup_per_cpu_areas(void) int i; unsigned long size; +#ifdef CONFIG_HOTPLUG_CPU + prefill_possible_map(); +#endif + /* Copy section for each CPU (we discard the original) */ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES); #ifdef CONFIG_MODULES diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index e12d7ba..658a81b 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -892,7 +892,7 @@ static __init void disable_smp(void) * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range. * - Ashok Raj */ -static void prefill_possible_map(void) +__init void prefill_possible_map(void) { int i; for (i = 0; i < NR_CPUS; i++) @@ -967,10 +967,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) current_cpu_data = boot_cpu_data; current_thread_info()->cpu = 0; /* needed? */ -#ifdef CONFIG_HOTPLUG_CPU - prefill_possible_map(); -#endif - if (smp_sanity_check(max_cpus) < 0) { printk(KERN_INFO "SMP disabled\n"); disable_smp(); diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index 24e3261..c57ce40 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h @@ -81,6 +81,7 @@ static inline int hard_smp_processor_id(void) extern int safe_smp_processor_id(void); extern int __cpu_disable(void); extern void __cpu_die(unsigned int cpu); +extern void prefill_possible_map(void); #endif /* !ASSEMBLY */ -- cgit v0.10.2 From 3c92c2ba33cd7d666c5f83cc32aa590e794e91b0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 11 Oct 2005 01:28:33 +0200 Subject: [PATCH] i386: Don't discard upper 32bits of HWCR on K8 Need to use long long, not long when RMWing a MSR. I think it's harmless right now, but still should be better fixed if AMD adds any bits in the upper 32bit of HWCR. Bug was introduced with the TLB flush filter fix for i386 Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 4c1ddf2b..53a1681 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -29,7 +29,7 @@ static void __init init_amd(struct cpuinfo_x86 *c) int r; #ifdef CONFIG_SMP - unsigned long value; + unsigned long long value; /* Disable TLB flush filter by setting HWCR.FFDIS on K8 * bit 6 of msr C001_0015 -- cgit v0.10.2 From 907a42617970a159361f17ef9a63f04d276995ab Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 10 Oct 2005 18:19:19 -0700 Subject: Linux v2.6.14-rc4 diff --git a/Makefile b/Makefile index fdb96bc..504ba3c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 14 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc4 NAME=Affluent Albatross # *DOCUMENTATION* -- cgit v0.10.2 From b8df110fea555d5088bba67f446c2435104405be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 10 Oct 2005 20:43:22 -0700 Subject: [SPARC64]: Fix oops on runlevel change with serial console. Incorrect uart_write_wakeup() calls cause reference to a NULL tty pointer in sunsab and sunzilog serial drivers. Signed-off-by: David S. Miller diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index e971156..ba9381f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -274,7 +274,6 @@ static void transmit_chars(struct uart_sunsab_port *up, if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { up->interrupt_mask1 |= SAB82532_IMR1_XPR; writeb(up->interrupt_mask1, &up->regs->w.imr1); - uart_write_wakeup(&up->port); return; } diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d754457..7653d6c 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -517,10 +517,9 @@ static void sunzilog_transmit_chars(struct uart_sunzilog_port *up, if (up->port.info == NULL) goto ack_tx_int; xmit = &up->port.info->xmit; - if (uart_circ_empty(xmit)) { - uart_write_wakeup(&up->port); + if (uart_circ_empty(xmit)) goto ack_tx_int; - } + if (uart_tx_stopped(&up->port)) goto ack_tx_int; -- cgit v0.10.2 From 85d9b05d9b1edad9a2630584754720a957ab0a2a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:47:42 -0700 Subject: [NETFILTER] PPTP helper: Add missing Kconfig dependency PPTP should not be selectable without conntrack enabled Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a765972..4b6f807 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -139,6 +139,7 @@ config IP_NF_AMANDA config IP_NF_PPTP tristate 'PPTP protocol support' + depends on IP_NF_CONNTRACK help This module adds support for PPTP (Point to Point Tunnelling Protocol, RFC2637) connection tracking and NAT. -- cgit v0.10.2 From f40863cec87464f3f4ec3a6c00e3fda3bbb0c91b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:51:53 -0700 Subject: [NETFILTER] ipt_ULOG: Mark ipt_ULOG as OBSOLETE Similar to nfnetlink_queue and ip_queue, we mark ipt_ULOG as obsolete. This should have been part of the original nfnetlink_log merge, but I somehow missed it. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 4b6f807..7d917e4 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -499,9 +499,14 @@ config IP_NF_TARGET_LOG To compile it as a module, choose M here. If unsure, say N. config IP_NF_TARGET_ULOG - tristate "ULOG target support" + tristate "ULOG target support (OBSOLETE)" depends on IP_NF_IPTABLES ---help--- + + This option enables the old IPv4-only "ipt_ULOG" implementation + which has been obsoleted by the new "nfnetlink_log" code (see + CONFIG_NETFILTER_NETLINK_LOG). + This option adds a `ULOG' target, which allows you to create rules in any iptables table. The packet is passed to a userspace logging daemon using netlink multicast sockets; unlike the LOG target -- cgit v0.10.2 From ebe0bbf06c9e03613bdcb6b5a704595a9344b7ff Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:52:19 -0700 Subject: [NETFILTER] nfnetlink: use highest bit of nfa_type to indicate nested TLV As Henrik Nordstrom pointed out, all our efforts with "split endian" (i.e. host byte order tags, net byte order values) are useless, unless a parser can determine whether an attribute is nested or not. This patch steals the highest bit of nfattr.nfa_type to indicate whether the data payload contains a nested nfattr (1) or not (0). This will break userspace compatibility, but luckily no kernel with nfnetlink was released so far. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 1d5b10a..f08e870 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -41,11 +41,15 @@ enum nfnetlink_groups { struct nfattr { u_int16_t nfa_len; - u_int16_t nfa_type; + u_int16_t nfa_type; /* we use 15 bits for the type, and the highest + * bit to indicate whether the payload is nested */ } __attribute__ ((packed)); -/* FIXME: Shamelessly copy and pasted from rtnetlink.h, it's time - * to put this in a generic file */ +/* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from + * rtnetlink.h, it's time to put this in a generic file */ + +#define NFNL_NFA_NEST 0x8000 +#define NFA_TYPE(attr) ((attr)->nfa_type & 0x7fff) #define NFA_ALIGNTO 4 #define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1)) @@ -59,7 +63,7 @@ struct nfattr #define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0)) #define NFA_NEST(skb, type) \ ({ struct nfattr *__start = (struct nfattr *) (skb)->tail; \ - NFA_PUT(skb, type, 0, NULL); \ + NFA_PUT(skb, (NFNL_NFA_NEST | type), 0, NULL); \ __start; }) #define NFA_NEST_END(skb, start) \ ({ (start)->nfa_len = ((skb)->tail - (unsigned char *) (start)); \ diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 1caaca0..4bc27a6 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -133,7 +133,7 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) memset(tb, 0, sizeof(struct nfattr *) * maxattr); while (NFA_OK(nfa, len)) { - unsigned flavor = nfa->nfa_type; + unsigned flavor = NFA_TYPE(nfa); if (flavor && flavor <= maxattr) tb[flavor-1] = nfa; nfa = NFA_NEXT(nfa, len); @@ -177,7 +177,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); while (NFA_OK(attr, attrlen)) { - unsigned flavor = attr->nfa_type; + unsigned flavor = NFA_TYPE(attr); if (flavor) { if (flavor > attr_count) return -EINVAL; -- cgit v0.10.2 From b3a91d037a2575040f9b6a483f60c407a3d80368 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:52:36 -0700 Subject: [NETFILTER] nat: remove bogus structure member When 'rustynat' was merged in 2.6.12, the use of the "helper" pointer of struct ipt_nat_info was obsoleted, but the pointer not removed from the struct. This patch removes the pointer, thereby yet again shrinking struct ip_conntrack. Discovered-by: Rusty Russell Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index e201ec6..41a107d 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -58,10 +58,6 @@ extern rwlock_t ip_nat_lock; struct ip_nat_info { struct list_head bysource; - - /* Helper (NULL if none). */ - struct ip_nat_helper *helper; - struct ip_nat_seq seq[IP_CT_DIR_MAX]; }; -- cgit v0.10.2 From d000eaf7720cb12cd03cd3d55f71be44357d27a9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:52:51 -0700 Subject: [NETFILTER] conntrack_netlink: Fix endian issue with status from userspace When we send "status" from userspace, we forget to convert the endianness. This patch adds the reqired conversion. Thanks to Pablo Neira for discovering this. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index b08a432..eade2749 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -833,7 +833,8 @@ out: static inline int ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[]) { - unsigned long d, status = *(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]); + unsigned long d; + unsigned status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1])); d = ct->status ^ status; if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) -- cgit v0.10.2 From a1bcc3f26885b0a8bf04799551de2e9574ccbda1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 10 Oct 2005 20:53:16 -0700 Subject: [NETFILTER] ctnetlink: ICMP ID is not mandatory The ID is only required by ICMP type 8 (echo), so it's not mandatory for all sort of ICMP connections. This patch makes mandatory only the type and the code for ICMP netlink messages. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 838d1d6..98f0015 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -296,8 +296,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], struct ip_conntrack_tuple *tuple) { if (!tb[CTA_PROTO_ICMP_TYPE-1] - || !tb[CTA_PROTO_ICMP_CODE-1] - || !tb[CTA_PROTO_ICMP_ID-1]) + || !tb[CTA_PROTO_ICMP_CODE-1]) return -1; tuple->dst.u.icmp.type = -- cgit v0.10.2 From 5bbc243aafff9ad653dc7a9fa7bcaf0b4631355a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 20:54:01 -0700 Subject: [NETFILTER]: Add missing include to ip_conntrack_tuple.h Without this #include, __be16 is not defined and userspace programs will break. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h index 20e43f0..3232db1 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h @@ -1,6 +1,8 @@ #ifndef _IP_CONNTRACK_TUPLE_H #define _IP_CONNTRACK_TUPLE_H +#include + /* A `tuple' is a structure containing the information to uniquely identify a connection. ie. if two packets have the same tuple, they are in the same connection; if not, they are not. -- cgit v0.10.2 From e1c73b78e3706bd3c336d4730a01dd4081dfb7ee Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 10 Oct 2005 20:55:49 -0700 Subject: [NETFILTER] ctnetlink: add one nesting level for TCP state To keep consistency, the TCP private protocol information is nested attributes under CTA_PROTOINFO_TCP. This way the sequence of attributes to access the TCP state information looks like here below: CTA_PROTOINFO CTA_PROTOINFO_TCP CTA_PROTOINFO_TCP_STATE instead of: CTA_PROTOINFO CTA_PROTOINFO_TCP_STATE Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 5c55751..fb55110 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -70,11 +70,18 @@ enum ctattr_l4proto { enum ctattr_protoinfo { CTA_PROTOINFO_UNSPEC, - CTA_PROTOINFO_TCP_STATE, + CTA_PROTOINFO_TCP, __CTA_PROTOINFO_MAX }; #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) +enum ctattr_protoinfo_tcp { + CTA_PROTOINFO_TCP_UNSPEC, + CTA_PROTOINFO_TCP_STATE, + __CTA_PROTOINFO_TCP_MAX +}; +#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) + enum ctattr_counters { CTA_COUNTERS_UNSPEC, CTA_COUNTERS_PACKETS, diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 121760d..75e27e6 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -341,11 +341,15 @@ static int tcp_print_conntrack(struct seq_file *s, static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa, const struct ip_conntrack *ct) { + struct nfattr *nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP); + read_lock_bh(&tcp_lock); NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t), &ct->proto.tcp.state); read_unlock_bh(&tcp_lock); + NFA_NEST_END(skb, nest_parms); + return 0; nfattr_failure: -- cgit v0.10.2 From 08eb8f124f990aa476589d1f7810f7ec7f259c08 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 10 Oct 2005 21:02:26 -0700 Subject: [SPARC32]: Revert IOMAP change eb98129eec7fa605f0407dfd92d40ee8ddf5cd9a Breakage noted by Al Viro. It breaks non-PCI builds, it's probably better to have a more direct implementation on sparc32, and which driver actually needs this is still questionable. We can resolve this in 2.6.15 Signed-off-by: David S. Miller diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index f7c51b8..6537445 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -21,10 +21,6 @@ config GENERIC_ISA_DMA bool default y -config GENERIC_IOMAP - bool - default y - source "init/Kconfig" menu "General machine setup" diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index 8a3aef1e..a698562 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -5,7 +5,6 @@ CONFIG_MMU=y CONFIG_UID16=y CONFIG_HIGHMEM=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_IOMAP=y # # Code maturity level options -- cgit v0.10.2 From a02a64223eddb410712b015fb3342c9a316ab70b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 10 Oct 2005 21:11:08 -0700 Subject: [IPSEC]: Use ALIGN macro in ESP This patch uses the macro ALIGN in all the applicable spots for ESP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 1b5a09d..e911c6d 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -42,10 +43,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esp = x->data; alen = esp->auth.icv_trunc_len; tfm = esp->conf.tfm; - blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3; - clen = (clen + 2 + blksize-1)&~(blksize-1); + blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); + clen = ALIGN(clen + 2, blksize); if (esp->conf.padlen) - clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); + clen = ALIGN(clen, esp->conf.padlen); if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) goto error; @@ -307,13 +308,13 @@ static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); if (x->props.mode) { - mtu = (mtu + 2 + blksize-1)&~(blksize-1); + mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ mtu += 2 + blksize; } if (esp->conf.padlen) - mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1); + mtu = ALIGN(mtu, esp->conf.padlen); return mtu + x->props.header_len + esp->auth.icv_trunc_len; } diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 9b27460..0c7d7b4 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -66,10 +67,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) alen = esp->auth.icv_trunc_len; tfm = esp->conf.tfm; - blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3; - clen = (clen + 2 + blksize-1)&~(blksize-1); + blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); + clen = ALIGN(clen + 2, blksize); if (esp->conf.padlen) - clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); + clen = ALIGN(clen, esp->conf.padlen); if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) { goto error; @@ -238,13 +239,13 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); if (x->props.mode) { - mtu = (mtu + 2 + blksize-1)&~(blksize-1); + mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ mtu += 2 + blksize; } if (esp->conf.padlen) - mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1); + mtu = ALIGN(mtu, esp->conf.padlen); return mtu + x->props.header_len + esp->auth.icv_full_len; } -- cgit v0.10.2 From d4875b049b2e6401a6e1fae90b7f09e20a636fcf Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 10 Oct 2005 21:11:34 -0700 Subject: [IPSEC] Fix block size/MTU bugs in ESP This patch fixes the following bugs in ESP: * Fix transport mode MTU overestimate. This means that the inner MTU is smaller than it needs be. Worse yet, given an input MTU which is a multiple of 4 it will always produce an estimate which is not a multiple of 4. For example, given a standard ESP/3DES/MD5 transform and an MTU of 1500, the resulting MTU for transport mode is 1462 when it should be 1464. The reason for this is because IP header lengths are always a multiple of 4 for IPv4 and 8 for IPv6. * Ensure that the block size is at least 4. This is required by RFC2406 and corresponds to what the esp_output function does. At the moment this only affects crypto_null as its block size is 1. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index e911c6d..1b18ce6 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -144,7 +144,7 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc struct ip_esp_hdr *esph; struct esp_data *esp = x->data; struct sk_buff *trailer; - int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int nfrags; @@ -305,13 +305,13 @@ static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); if (x->props.mode) { mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ - mtu += 2 + blksize; + mtu = ALIGN(mtu + 2, 4) + blksize - 4; } if (esp->conf.padlen) mtu = ALIGN(mtu, esp->conf.padlen); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 0c7d7b4..40d9a19 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -134,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru struct ipv6_esp_hdr *esph; struct esp_data *esp = x->data; struct sk_buff *trailer; - int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; @@ -236,13 +236,14 @@ out_nofree: static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); if (x->props.mode) { mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ - mtu += 2 + blksize; + u32 padsize = ((blksize - 1) & 7) + 1; + mtu = ALIGN(mtu + 2, padsize) + blksize - padsize; } if (esp->conf.padlen) mtu = ALIGN(mtu, esp->conf.padlen); -- cgit v0.10.2 From a051a8f7306476af0a74370ad56e793cb6c43bf7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 10 Oct 2005 21:21:10 -0700 Subject: [NETFILTER]: Use only 32bit counters for CONNTRACK_ACCT Initially we used 64bit counters for conntrack-based accounting, since we had no event mechanism to tell userspace that our counters are about to overflow. With nfnetlink_conntrack, we now have such a event mechanism and thus can save 16bytes per connection. Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index fb55110..116fcac 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -84,8 +84,10 @@ enum ctattr_protoinfo_tcp { enum ctattr_counters { CTA_COUNTERS_UNSPEC, - CTA_COUNTERS_PACKETS, - CTA_COUNTERS_BYTES, + CTA_COUNTERS_PACKETS, /* old 64bit counters */ + CTA_COUNTERS_BYTES, /* old 64bit counters */ + CTA_COUNTERS32_PACKETS, + CTA_COUNTERS32_BYTES, __CTA_COUNTERS_MAX }; #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1) diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 4ced387..d078bb9 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -117,6 +117,10 @@ enum ip_conntrack_events /* NAT info */ IPCT_NATINFO_BIT = 10, IPCT_NATINFO = (1 << IPCT_NATINFO_BIT), + + /* Counter highest bit has been set */ + IPCT_COUNTER_FILLING_BIT = 11, + IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), }; enum ip_conntrack_expect_events { @@ -192,8 +196,8 @@ do { \ struct ip_conntrack_counter { - u_int64_t packets; - u_int64_t bytes; + u_int32_t packets; + u_int32_t bytes; }; struct ip_conntrack_helper; diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index ea65dd3..07a80b5 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1119,7 +1119,7 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct, unsigned long extra_jiffies, int do_acct) { - int do_event = 0; + int event = 0; IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); IP_NF_ASSERT(skb); @@ -1129,13 +1129,13 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct, /* If not in hash table, timer will not be active yet */ if (!is_confirmed(ct)) { ct->timeout.expires = extra_jiffies; - do_event = 1; + event = IPCT_REFRESH; } else { /* Need del_timer for race avoidance (may already be dying). */ if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; add_timer(&ct->timeout); - do_event = 1; + event = IPCT_REFRESH; } } @@ -1144,14 +1144,17 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct, ct->counters[CTINFO2DIR(ctinfo)].packets++; ct->counters[CTINFO2DIR(ctinfo)].bytes += ntohs(skb->nh.iph->tot_len); + if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000) + || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000)) + event |= IPCT_COUNTER_FILLING; } #endif write_unlock_bh(&ip_conntrack_lock); /* must be unlocked when calling event cache */ - if (do_event) - ip_conntrack_event_cache(IPCT_REFRESH, skb); + if (event) + ip_conntrack_event_cache(event, skb); } #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index eade2749..06ed91e 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -177,11 +177,11 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct, struct nfattr *nest_count = NFA_NEST(skb, type); u_int64_t tmp; - tmp = cpu_to_be64(ct->counters[dir].packets); - NFA_PUT(skb, CTA_COUNTERS_PACKETS, sizeof(u_int64_t), &tmp); + tmp = htonl(ct->counters[dir].packets); + NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); - tmp = cpu_to_be64(ct->counters[dir].bytes); - NFA_PUT(skb, CTA_COUNTERS_BYTES, sizeof(u_int64_t), &tmp); + tmp = htonl(ct->counters[dir].bytes); + NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp); NFA_NEST_END(skb, nest_count); -- cgit v0.10.2 From 339231537506846cb232a2f0cc4a2c662b2d5b07 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 10 Oct 2005 21:23:28 -0700 Subject: [NETFILTER] ctnetlink: allow userspace to change TCP state This patch adds the ability of changing the state a TCP connection. I know that this must be used with care but it's required to provide a complete conntrack creation via conntrack_netlink. So I'll document this aspect on the upcoming docs. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h index b6b99be..2c76b87 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h @@ -52,6 +52,9 @@ struct ip_conntrack_protocol int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa, const struct ip_conntrack *ct); + /* convert nfnetlink attributes to protoinfo */ + int (*from_nfattr)(struct nfattr *tb[], struct ip_conntrack *ct); + int (*tuple_to_nfattr)(struct sk_buff *skb, const struct ip_conntrack_tuple *t); int (*nfattr_to_tuple)(struct nfattr *tb[], diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 75e27e6..d6701ca 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -356,6 +356,28 @@ nfattr_failure: read_unlock_bh(&tcp_lock); return -1; } + +static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) +{ + struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; + struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; + + if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) + goto nfattr_failure; + + if (!tb[CTA_PROTOINFO_TCP_STATE-1]) + return -EINVAL; + + write_lock_bh(&tcp_lock); + ct->proto.tcp.state = + *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]); + write_unlock_bh(&tcp_lock); + + return 0; + +nfattr_failure: + return -1; +} #endif static unsigned int get_conntrack_index(const struct tcphdr *tcph) @@ -1127,6 +1149,7 @@ struct ip_conntrack_protocol ip_conntrack_protocol_tcp = #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, + .from_nfattr = nfattr_to_tcp, .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr, .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple, #endif -- cgit v0.10.2 From 061cb4a0ec34a6e3069d5a1b3c547e55a71498c5 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 10 Oct 2005 21:23:46 -0700 Subject: [NETFILTER] ctnetlink: add support to change protocol info This patch add support to change the state of the private protocol information via conntrack_netlink. Signed-off-by: Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 06ed91e..166e606 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -949,6 +949,31 @@ ctnetlink_change_timeout(struct ip_conntrack *ct, struct nfattr *cda[]) return 0; } +static inline int +ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) +{ + struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1]; + struct ip_conntrack_protocol *proto; + u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; + int err = 0; + + if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) + goto nfattr_failure; + + proto = ip_conntrack_proto_find_get(npt); + if (!proto) + return -EINVAL; + + if (proto->from_nfattr) + err = proto->from_nfattr(tb, ct); + ip_conntrack_proto_put(proto); + + return err; + +nfattr_failure: + return -ENOMEM; +} + static int ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) { @@ -974,6 +999,12 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) return err; } + if (cda[CTA_PROTOINFO-1]) { + err = ctnetlink_change_protoinfo(ct, cda); + if (err < 0) + return err; + } + DEBUGP("all done\n"); return 0; } @@ -1003,6 +1034,12 @@ ctnetlink_create_conntrack(struct nfattr *cda[], if (err < 0) goto err; + if (cda[CTA_PROTOINFO-1]) { + err = ctnetlink_change_protoinfo(ct, cda); + if (err < 0) + return err; + } + ct->helper = ip_conntrack_helper_find_get(rtuple); add_timer(&ct->timeout); -- cgit v0.10.2 From 777b25a2fea7129222eb11fba55c0a67982383ff Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Oct 2005 21:24:20 -0700 Subject: [CCID]: Check if ccid is NULL in the hc_[tr]x_exit functions For consistency with ccid_exit and to fix a bug when IP_DCCP_UNLOAD_HACK is enabled as the control sock is not associated to any CCID. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 21e5514..c37eeea 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -110,14 +110,14 @@ static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk) static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk) { - if (ccid->ccid_hc_rx_exit != NULL && + if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL && dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL) ccid->ccid_hc_rx_exit(sk); } static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk) { - if (ccid->ccid_hc_tx_exit != NULL && + if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL && dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL) ccid->ccid_hc_tx_exit(sk); } -- cgit v0.10.2 From 2a9bc9bb4d3a4570a8a48aadf071b91e657adb89 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Oct 2005 21:25:00 -0700 Subject: [DCCP]: Transition from PARTOPEN to OPEN when receiving DATA packets Noticed by Andrea Bittau, that provided a patch that was modified to not transition from RESPOND to OPEN when receiving DATA packets. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/dccp/input.c b/net/dccp/input.c index 1b6b2cb..3454d59 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -375,6 +375,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk, case DCCP_PKT_RESET: inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); break; + case DCCP_PKT_DATA: + if (sk->sk_state == DCCP_RESPOND) + break; case DCCP_PKT_DATAACK: case DCCP_PKT_ACK: /* @@ -393,7 +396,8 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk, dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq; dccp_set_state(sk, DCCP_OPEN); - if (dh->dccph_type == DCCP_PKT_DATAACK) { + if (dh->dccph_type == DCCP_PKT_DATAACK || + dh->dccph_type == DCCP_PKT_DATA) { dccp_rcv_established(sk, skb, dh, len); queued = 1; /* packet was queued (by dccp_rcv_established) */ -- cgit v0.10.2 From eeb2b8560676e454ad37ee30b49bc7d897edc9be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 Oct 2005 21:25:23 -0700 Subject: [TWSK]: Grab the module refcount for timewait sockets This is required to avoid unloading a module that has active timewait sockets, such as DCCP. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 4ade56e..28f7b21 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -193,11 +194,13 @@ static inline u32 inet_rcv_saddr(const struct sock *sk) static inline void inet_twsk_put(struct inet_timewait_sock *tw) { if (atomic_dec_and_test(&tw->tw_refcnt)) { + struct module *owner = tw->tw_prot->owner; #ifdef SOCK_REFCNT_DEBUG printk(KERN_DEBUG "%s timewait_sock %p released\n", tw->tw_prot->name, tw); #endif kmem_cache_free(tw->tw_prot->twsk_slab, tw); + module_put(owner); } } diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index f9076ef..a010e9a 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -111,6 +111,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_prot = sk->sk_prot_creator; atomic_set(&tw->tw_refcnt, 1); inet_twsk_dead_node_init(tw); + __module_get(tw->tw_prot->owner); } return tw; -- cgit v0.10.2 From 875521ddccfa90d519cf31dfc8aa472f7f6325bb Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 11 Oct 2005 01:38:35 -0400 Subject: e100: revert CPU cycle saver microcode, it causes severe problems for certain NICs Reverting 685fac63f5ca6c5ca06bab641e1a32bbf9287e89: > [PATCH] e100: CPU cycle saver microcode > > > Add cpu cycle saver microcode to 8086:{1209/1229} other than ICH devices. > > Signed-off-by: Mallikarjuna R Chilakala > Signed-off-by: Ganesh Venkatesan > Signed-off-by: John Ronciak > Signed-off-by: Jeff Garzik diff --git a/drivers/net/e100.c b/drivers/net/e100.c index fbf1c06..40887f0 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -903,8 +903,8 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data) static void e100_get_defaults(struct nic *nic) { - struct param_range rfds = { .min = 16, .max = 256, .count = 256 }; - struct param_range cbs = { .min = 64, .max = 256, .count = 128 }; + struct param_range rfds = { .min = 16, .max = 256, .count = 64 }; + struct param_range cbs = { .min = 64, .max = 256, .count = 64 }; pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ @@ -1007,213 +1007,25 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); } -/********************************************************/ -/* Micro code for 8086:1229 Rev 8 */ -/********************************************************/ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for 8086:1229 Rev 9 */ -/********************************************************/ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* Micro code for the 8086:1229 Rev F/10 */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \ -0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -} - static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb) { -/* *INDENT-OFF* */ - static struct { - u32 ucode[UCODE_SIZE + 1]; - u8 mac; - u8 timer_dword; - u8 bundle_dword; - u8 min_size_dword; - } ucode_opts[] = { - { D101M_B_RCVBUNDLE_UCODE, - mac_82559_D101M, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_RCVBUNDLE_UCODE, - mac_82559_D101S, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_F, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { D102_E_RCVBUNDLE_UCODE, - mac_82551_10, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { {0}, 0, 0, 0, 0} - }, *opts; -/* *INDENT-ON* */ - -#define BUNDLESMALL 1 -#define BUNDLEMAX 50 -#define INTDELAY 15000 - - opts = ucode_opts; - - /* do not load u-code for ICH devices */ - if (nic->flags & ich) - return; - - /* Search for ucode match against h/w rev_id */ - while (opts->mac) { - if (nic->mac == opts->mac) { - int i; - u32 *ucode = opts->ucode; - - /* Insert user-tunable settings */ - ucode[opts->timer_dword] &= 0xFFFF0000; - ucode[opts->timer_dword] |= - (u16) INTDELAY; - ucode[opts->bundle_dword] &= 0xFFFF0000; - ucode[opts->bundle_dword] |= (u16) BUNDLEMAX; - ucode[opts->min_size_dword] &= 0xFFFF0000; - ucode[opts->min_size_dword] |= - (BUNDLESMALL) ? 0xFFFF : 0xFF80; - - for(i = 0; i < UCODE_SIZE; i++) - cb->u.ucode[i] = cpu_to_le32(ucode[i]); - cb->command = cpu_to_le16(cb_ucode); - return; - } - opts++; - } + int i; + static const u32 ucode[UCODE_SIZE] = { + /* NFS packets are misinterpreted as TCO packets and + * incorrectly routed to the BMC over SMBus. This + * microcode patch checks the fragmented IP bit in the + * NFS/UDP header to distinguish between NFS and TCO. */ + 0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, + 0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, + 0x00906EFD, 0x00900EFD, 0x00E00EF8, + }; - cb->command = cpu_to_le16(cb_nop); + if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) { + for(i = 0; i < UCODE_SIZE; i++) + cb->u.ucode[i] = cpu_to_le32(ucode[i]); + cb->command = cpu_to_le16(cb_ucode); + } else + cb->command = cpu_to_le16(cb_nop); } static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, -- cgit v0.10.2 From 9621904012de3c8d0d4e2904dcc7170b3012119e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 11 Oct 2005 01:52:39 -0400 Subject: sata_nv: Fixed bug introduced by 0.08's MCP51 and MCP55 support. diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index c05653c..cb832b0 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -29,6 +29,8 @@ * NV-specific details such as register offsets, SATA phy location, * hotplug info, etc. * + * 0.09 + * - Fixed bug introduced by 0.08's MCP51 and MCP55 support. * * 0.08 * - Added support for MCP51 and MCP55. @@ -132,9 +134,7 @@ enum nv_host_type GENERIC, NFORCE2, NFORCE3, - CK804, - MCP51, - MCP55 + CK804 }; static struct pci_device_id nv_pci_tbl[] = { @@ -153,13 +153,13 @@ static struct pci_device_id nv_pci_tbl[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP51 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, MCP55 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, -- cgit v0.10.2 From e5945b4f605d1479d5b44252a2c691168c5d38d6 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 11 Oct 2005 08:28:59 -0700 Subject: [PATCH] s390: ccw device reconnect oops. Search for a disconnect ccw_device on the ccw bus rather than on the css bus (was a typo in patch I did for the klist conversion). A cast to an embedding ccw_device from an embedded device in a struct subchannel will lead us to oopses. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 14c76f5..9adc11e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -544,7 +544,7 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) .sibling = sibling, }; - dev = bus_find_device(&css_bus_type, NULL, &data, match_devno); + dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno); return dev ? to_ccwdev(dev) : NULL; } -- cgit v0.10.2 From e4314bf496bb7bb9acd754aeb319c30869bc8d76 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 11 Oct 2005 08:29:00 -0700 Subject: [PATCH] ppc64: Fix PCI hotplug pSeries_irq_bus_setup is marked __devinit but references s7a_workaround which is marked __initdata. Depending on who got the memory for s7a_workaround (and if the value was now positive), it was possible for PCI hotplugged devices to have 3 subtracted from their interrupt number. This would happen randomly and caused me much confusion :) Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c index 1f5f141..928f8fe 100644 --- a/arch/ppc64/kernel/pSeries_pci.c +++ b/arch/ppc64/kernel/pSeries_pci.c @@ -32,7 +32,7 @@ #include "pci.h" -static int __initdata s7a_workaround = -1; +static int __devinitdata s7a_workaround = -1; #if 0 void pcibios_name_device(struct pci_dev *dev) @@ -60,7 +60,7 @@ void pcibios_name_device(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device); #endif -static void __init check_s7a(void) +static void __devinit check_s7a(void) { struct device_node *root; char *model; -- cgit v0.10.2 From ad6ce87e5bd4440a6ce9aa9f8cda795b9e902eff Mon Sep 17 00:00:00 2001 From: Abhay Salunke Date: Tue, 11 Oct 2005 08:29:02 -0700 Subject: [PATCH] dell_rbu: changes in packet update mechanism In the current dell_rbu code ver 2.0 the packet update mechanism makes the user app dump every individual packet in to the driver. This adds in efficiency as every packet update makes the /sys/class/firmware/dell_rbu/loading and data files to disappear and reappear again. Thus the user app needs to wait for the files to reappear to dump another packet. This slows down the packet update tremendously in case of large number of packets. I am submitting a new patch for dell_rbu which will change the way we do packet updates; In the new method the user app will create a new single file which has already packetized the rbu image and all the packets are now staged in this file. This driver also creates a new entry in /sys/devices/platform/dell_rbu/packet_size ; the user needs to echo the packet size here before downloading the packet file. The user should do the following: create one single file which has all the packets stacked together. echo the packet size in to /sys/devices/platform/dell_rbu/packet_size. echo 1 > /sys/class/firmware/dell_rbu/loading cat the packetfile > /sys/class/firmware/dell_rbu/data echo 0 > /sys/class/firmware/dell_rbu/loading The driver takes the file which came through /sys/class/firmware/dell_rbu/data and takes chunks of paket_size data from it and place in contiguous memory. This makes packet update process very efficient and fast. As all the packet update happens in one single operation. The user can still read back the downloaded file from /sys/devices/platform/dell_rbu/data. Signed-off-by: Abhay Salunke Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index 95d7f62..941343a 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt @@ -35,6 +35,7 @@ The driver load creates the following directories under the /sys file system. /sys/class/firmware/dell_rbu/data /sys/devices/platform/dell_rbu/image_type /sys/devices/platform/dell_rbu/data +/sys/devices/platform/dell_rbu/packet_size The driver supports two types of update mechanism; monolithic and packetized. These update mechanism depends upon the BIOS currently running on the system. @@ -47,8 +48,26 @@ By default the driver uses monolithic memory for the update type. This can be changed to packets during the driver load time by specifying the load parameter image_type=packet. This can also be changed later as below echo packet > /sys/devices/platform/dell_rbu/image_type -Also echoing either mono ,packet or init in to image_type will free up the -memory allocated by the driver. + +In packet update mode the packet size has to be given before any packets can +be downloaded. It is done as below +echo XXXX > /sys/devices/platform/dell_rbu/packet_size +In the packet update mechanism, the user neesd to create a new file having +packets of data arranged back to back. It can be done as follows +The user creates packets header, gets the chunk of the BIOS image and +placs it next to the packetheader; now, the packetheader + BIOS image chunk +added to geather should match the specified packet_size. This makes one +packet, the user needs to create more such packets out of the entire BIOS +image file and then arrange all these packets back to back in to one single +file. +This file is then copied to /sys/class/firmware/dell_rbu/data. +Once this file gets to the driver, the driver extracts packet_size data from +the file and spreads it accross the physical memory in contiguous packet_sized +space. +This method makes sure that all the packets get to the driver in a single operation. + +In monolithic update the user simply get the BIOS image (.hdr file) and copies +to the data file as is without any change to the BIOS image itself. Do the steps below to download the BIOS image. 1) echo 1 > /sys/class/firmware/dell_rbu/loading @@ -58,7 +77,10 @@ Do the steps below to download the BIOS image. The /sys/class/firmware/dell_rbu/ entries will remain till the following is done. echo -1 > /sys/class/firmware/dell_rbu/loading. -Until this step is completed the drivr cannot be unloaded. +Until this step is completed the driver cannot be unloaded. +Also echoing either mono ,packet or init in to image_type will free up the +memory allocated by the driver. + If an user by accident executes steps 1 and 3 above without executing step 2; it will make the /sys/class/firmware/dell_rbu/ entries to disappear. The entries can be recreated by doing the following @@ -66,15 +88,11 @@ echo init > /sys/devices/platform/dell_rbu/image_type NOTE: echoing init in image_type does not change it original value. Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to -read back the image downloaded. This is useful in case of packet update -mechanism where the above steps 1,2,3 will repeated for every packet. -By reading the /sys/devices/platform/dell_rbu/data file all packet data -downloaded can be verified in a single file. -The packets are arranged in this file one after the other in a FIFO order. +read back the image downloaded. NOTE: -This driver requires a patch for firmware_class.c which has the addition -of request_firmware_nowait_nohotplug function to wortk +This driver requires a patch for firmware_class.c which has the modified +request_firmware_nowait function. Also after updating the BIOS image an user mdoe application neeeds to execute code which message the BIOS update request to the BIOS. So on the next reboot the BIOS knows about the new image downloaded and it updates it self. diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index b667823..4f4ba9b 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -50,7 +50,7 @@ MODULE_AUTHOR("Abhay Salunke "); MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); MODULE_LICENSE("GPL"); -MODULE_VERSION("2.0"); +MODULE_VERSION("3.0"); #define BIOS_SCAN_LIMIT 0xffffffff #define MAX_IMAGE_LENGTH 16 @@ -62,15 +62,16 @@ static struct _rbu_data { int dma_alloc; spinlock_t lock; unsigned long packet_read_count; - unsigned long packet_write_count; unsigned long num_packets; unsigned long packetsize; + unsigned long imagesize; int entry_created; } rbu_data; static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; module_param_string(image_type, image_type, sizeof (image_type), 0); -MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); +MODULE_PARM_DESC(image_type, + "BIOS image type. choose- mono or packet or init"); struct packet_data { struct list_head list; @@ -88,55 +89,13 @@ static dma_addr_t dell_rbu_dmaaddr; static void init_packet_head(void) { INIT_LIST_HEAD(&packet_data_head.list); - rbu_data.packet_write_count = 0; rbu_data.packet_read_count = 0; rbu_data.num_packets = 0; rbu_data.packetsize = 0; + rbu_data.imagesize = 0; } -static int fill_last_packet(void *data, size_t length) -{ - struct list_head *ptemp_list; - struct packet_data *packet = NULL; - int packet_count = 0; - - pr_debug("fill_last_packet: entry \n"); - - if (!rbu_data.num_packets) { - pr_debug("fill_last_packet: num_packets=0\n"); - return -ENOMEM; - } - - packet_count = rbu_data.num_packets; - - ptemp_list = (&packet_data_head.list)->prev; - - packet = list_entry(ptemp_list, struct packet_data, list); - - if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { - pr_debug("dell_rbu:%s: packet size data " - "overrun\n", __FUNCTION__); - return -EINVAL; - } - - pr_debug("fill_last_packet : buffer = %p\n", packet->data); - - memcpy((packet->data + rbu_data.packet_write_count), data, length); - - if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) { - /* - * this was the last data chunk in the packet - * so reinitialize the packet data counter to zero - */ - rbu_data.packet_write_count = 0; - } else - rbu_data.packet_write_count += length; - - pr_debug("fill_last_packet: exit \n"); - return 0; -} - -static int create_packet(size_t length) +static int create_packet(void *data, size_t length) { struct packet_data *newpacket; int ordernum = 0; @@ -186,9 +145,11 @@ static int create_packet(size_t length) INIT_LIST_HEAD(&newpacket->list); list_add_tail(&newpacket->list, &packet_data_head.list); /* - * packets have fixed size + * packets may not have fixed size */ - newpacket->length = rbu_data.packetsize; + newpacket->length = length; + + memcpy(newpacket->data, data, length); pr_debug("create_packet: exit \n"); @@ -198,13 +159,37 @@ static int create_packet(size_t length) static int packetize_data(void *data, size_t length) { int rc = 0; + int done = 0; + int packet_length; + u8 *temp; + u8 *end = (u8 *) data + length; + pr_debug("packetize_data: data length %d\n", length); + if (!rbu_data.packetsize) { + printk(KERN_WARNING + "dell_rbu: packetsize not specified\n"); + return -EIO; + } - if (!rbu_data.packet_write_count) { - if ((rc = create_packet(length))) + temp = (u8 *) data; + + /* packetize the hunk */ + while (!done) { + if ((temp + rbu_data.packetsize) < end) + packet_length = rbu_data.packetsize; + else { + /* this is the last packet */ + packet_length = end - temp; + done = 1; + } + + if ((rc = create_packet(temp, packet_length))) return rc; + + pr_debug("%lu:%lu\n", temp, (end - temp)); + temp += packet_length; } - if ((rc = fill_last_packet(data, length))) - return rc; + + rbu_data.imagesize = length; return rc; } @@ -243,7 +228,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list, return bytes_copied; } -static int packet_read_list(char *data, size_t *pread_length) +static int packet_read_list(char *data, size_t * pread_length) { struct list_head *ptemp_list; int temp_count = 0; @@ -303,10 +288,9 @@ static void packet_empty_list(void) newpacket->ordernum); kfree(newpacket); } - rbu_data.packet_write_count = 0; rbu_data.packet_read_count = 0; rbu_data.num_packets = 0; - rbu_data.packetsize = 0; + rbu_data.imagesize = 0; } /* @@ -425,7 +409,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) size_t bytes_left; size_t data_length; char *ptempBuf = buffer; - unsigned long imagesize; /* check to see if we have something to return */ if (rbu_data.num_packets == 0) { @@ -434,22 +417,20 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) goto read_rbu_data_exit; } - imagesize = rbu_data.num_packets * rbu_data.packetsize; - - if (pos > imagesize) { + if (pos > rbu_data.imagesize) { retval = 0; printk(KERN_WARNING "dell_rbu:read_packet_data: " "data underrun\n"); goto read_rbu_data_exit; } - bytes_left = imagesize - pos; + bytes_left = rbu_data.imagesize - pos; data_length = min(bytes_left, count); if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) goto read_rbu_data_exit; - if ((pos + count) > imagesize) { + if ((pos + count) > rbu_data.imagesize) { rbu_data.packet_read_count = 0; /* this was the last copy */ retval = bytes_left; @@ -499,7 +480,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) } static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) + loff_t pos, size_t count) { ssize_t ret_count = 0; @@ -531,13 +512,18 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) memcpy(rbu_data.image_update_buffer, fw->data, fw->size); } else if (!strcmp(image_type, "packet")) { - if (!rbu_data.packetsize) - rbu_data.packetsize = fw->size; - else if (rbu_data.packetsize != fw->size) { + /* + * we need to free previous packets if a + * new hunk of packets needs to be downloaded + */ + packet_empty_list(); + if (packetize_data(fw->data, fw->size)) + /* Incase something goes wrong when we are + * in middle of packetizing the data, we + * need to free up whatever packets might + * have been created before we quit. + */ packet_empty_list(); - rbu_data.packetsize = fw->size; - } - packetize_data(fw->data, fw->size); } else pr_debug("invalid image type specified.\n"); spin_unlock(&rbu_data.lock); @@ -553,7 +539,7 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) } static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) + loff_t pos, size_t count) { int size = 0; if (!pos) @@ -562,7 +548,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, } static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, - loff_t pos, size_t count) + loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; @@ -621,25 +607,49 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, return rc; } +static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) +{ + int size = 0; + if (!pos) { + spin_lock(&rbu_data.lock); + size = sprintf(buffer, "%lu\n", rbu_data.packetsize); + spin_unlock(&rbu_data.lock); + } + return size; +} + +static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, + loff_t pos, size_t count) +{ + unsigned long temp; + spin_lock(&rbu_data.lock); + packet_empty_list(); + sscanf(buffer, "%lu", &temp); + if (temp < 0xffffffff) + rbu_data.packetsize = temp; + + spin_unlock(&rbu_data.lock); + return count; +} + static struct bin_attribute rbu_data_attr = { - .attr = { - .name = "data", - .owner = THIS_MODULE, - .mode = 0444, - }, + .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, .read = read_rbu_data, }; static struct bin_attribute rbu_image_type_attr = { - .attr = { - .name = "image_type", - .owner = THIS_MODULE, - .mode = 0644, - }, + .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, .read = read_rbu_image_type, .write = write_rbu_image_type, }; +static struct bin_attribute rbu_packet_size_attr = { + .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644}, + .read = read_rbu_packet_size, + .write = write_rbu_packet_size, +}; + static int __init dcdrbu_init(void) { int rc = 0; @@ -657,6 +667,8 @@ static int __init dcdrbu_init(void) sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); + sysfs_create_bin_file(&rbu_device->dev.kobj, + &rbu_packet_size_attr); rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); -- cgit v0.10.2 From 19cba8abd6ca09527c194864ae651db65cbacfe1 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Tue, 11 Oct 2005 08:29:03 -0700 Subject: [PATCH] v9fs: remove additional buffer allocation from v9fs_file_read and v9fs_file_write v9fs_file_read and v9fs_file_write use kmalloc to allocate buffers as big as the data buffer received as parameter. kmalloc cannot be used to allocate buffers bigger than 128K, so reading/writing data in chunks bigger than 128k fails. This patch reorganizes v9fs_file_read and v9fs_file_write to allocate only buffers as big as the maximum data that can be sent in one 9P message. Signed-off-by: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a4799e9..bbc3cc6 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -175,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) } /** - * v9fs_read - read from a file (internal) + * v9fs_file_read - read from a file * @filep: file pointer to read * @data: data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ - static ssize_t -v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) +v9fs_file_read(struct file *filp, char __user * data, size_t count, + loff_t * offset) { struct inode *inode = filp->f_dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); @@ -194,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) int rsize = 0; int result = 0; int total = 0; + int n; dprintk(DEBUG_VFS, "\n"); @@ -216,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) } else *offset += result; - /* XXX - extra copy */ - memcpy(buffer, fcall->params.rread.data, result); + n = copy_to_user(data, fcall->params.rread.data, result); + if (n) { + dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); + kfree(fcall); + return -EFAULT; + } + count -= result; - buffer += result; + data += result; total += result; kfree(fcall); @@ -232,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) } /** - * v9fs_file_read - read from a file - * @filep: file pointer to read - * @data: data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ - -static ssize_t -v9fs_file_read(struct file *filp, char __user * data, size_t count, - loff_t * offset) -{ - int retval = -1; - int ret = 0; - char *buffer; - - buffer = kmalloc(count, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - retval = v9fs_read(filp, buffer, count, offset); - if (retval > 0) { - if ((ret = copy_to_user(data, buffer, retval)) != 0) { - dprintk(DEBUG_ERROR, "Problem copying to user %d\n", - ret); - retval = ret; - } - } - - kfree(buffer); - - return retval; -} - -/** - * v9fs_write - write to a file + * v9fs_file_write - write to a file * @filep: file pointer to write * @data: data buffer to write data from * @count: size of buffer @@ -276,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, */ static ssize_t -v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) +v9fs_file_write(struct file *filp, const char __user * data, + size_t count, loff_t * offset) { struct inode *inode = filp->f_dentry->d_inode; struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); @@ -286,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) int result = -EIO; int rsize = 0; int total = 0; + char *buf; - dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, + dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, (int)*offset); rsize = v9ses->maxdata - V9FS_IOHDRSZ; if (v9fid->iounit != 0 && rsize > v9fid->iounit) rsize = v9fid->iounit; - dump_data(buffer, count); + buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); + if (!buf) + return -ENOMEM; do { if (count < rsize) rsize = count; - result = - v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); + result = copy_from_user(buf, data, rsize); + if (result) { + dprintk(DEBUG_ERROR, "Problem copying from user\n"); + kfree(buf); + return -EFAULT; + } + + dump_data(buf, rsize); + result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); if (result < 0) { eprintk(KERN_ERR, "error while writing: %s(%d)\n", FCALL_ERROR(fcall), result); kfree(fcall); + kfree(buf); return result; } else *offset += result; kfree(fcall); + fcall = NULL; if (result != rsize) { eprintk(KERN_ERR, @@ -319,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) } count -= result; - buffer += result; + data += result; total += result; } while (count); + kfree(buf); return total; } -/** - * v9fs_file_write - write to a file - * @filep: file pointer to write - * @data: data buffer to write data from - * @count: size of buffer - * @offset: offset at which to write data - * - */ - -static ssize_t -v9fs_file_write(struct file *filp, const char __user * data, - size_t count, loff_t * offset) -{ - int ret = -1; - char *buffer; - - buffer = kmalloc(count, GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; - - ret = copy_from_user(buffer, data, count); - if (ret) { - dprintk(DEBUG_ERROR, "Problem copying from user\n"); - ret = -EFAULT; - } else { - ret = v9fs_write(filp, buffer, count, offset); - } - - kfree(buffer); - - return ret; -} - struct file_operations v9fs_file_operations = { .llseek = generic_file_llseek, .read = v9fs_file_read, -- cgit v0.10.2 From 22c1ea44f0d33eda532883858b6cdabc5f265b66 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 11 Oct 2005 08:29:05 -0700 Subject: [PATCH] nfsacl: Solaris VxFS compatibility fix Here is a compatibility fix between Linux and Solaris when used with VxFS filesystems: Solaris usually accepts acl entries in any order, but with VxFS it replies with NFSERR_INVAL when it sees a four-entry acl that is not in canonical form. It may also fail with other non-canonical acls -- I can't tell, because that case never triggers: We only send non-canonical acls when we fake up an ACL_MASK entry. Instead of adding fake ACL_MASK entries at the end, inserting them in the correct position makes Solaris+VxFS happy. The Linux client and server sides don't care about entry order. The three-entry-acl special case in which we need a fake ACL_MASK entry was handled in xdr_nfsace_encode. The patch moves this into nfsacl_encode. Signed-off-by: Andreas Gruenbacher Acked-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 251e5a1..0c2be8c 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) (struct nfsacl_encode_desc *) desc; u32 *p = (u32 *) elem; - if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { - struct posix_acl_entry *entry = - &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; + struct posix_acl_entry *entry = + &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; - *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); - switch(entry->e_tag) { - case ACL_USER_OBJ: - *p++ = htonl(nfsacl_desc->uid); - break; - case ACL_GROUP_OBJ: - *p++ = htonl(nfsacl_desc->gid); - break; - case ACL_USER: - case ACL_GROUP: - *p++ = htonl(entry->e_id); - break; - default: /* Solaris depends on that! */ - *p++ = 0; - break; - } - *p++ = htonl(entry->e_perm & S_IRWXO); - } else { - const struct posix_acl_entry *pa, *pe; - int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; - - FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { - if (pa->e_tag == ACL_GROUP_OBJ) { - group_obj_perm = pa->e_perm & S_IRWXO; - break; - } - } - /* fake up ACL_MASK entry */ - *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); - *p++ = htonl(0); - *p++ = htonl(group_obj_perm); + *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); + switch(entry->e_tag) { + case ACL_USER_OBJ: + *p++ = htonl(nfsacl_desc->uid); + break; + case ACL_GROUP_OBJ: + *p++ = htonl(nfsacl_desc->gid); + break; + case ACL_USER: + case ACL_GROUP: + *p++ = htonl(entry->e_id); + break; + default: /* Solaris depends on that! */ + *p++ = 0; + break; } - + *p++ = htonl(entry->e_perm & S_IRWXO); return 0; } @@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, .gid = inode->i_gid, }; int err; + struct posix_acl *acl2 = NULL; if (entries > NFS_ACL_MAX_ENTRIES || xdr_encode_word(buf, base, entries)) return -EINVAL; + if (encode_entries && acl && acl->a_count == 3) { + /* Fake up an ACL_MASK entry. */ + acl2 = posix_acl_alloc(4, GFP_KERNEL); + if (!acl2) + return -ENOMEM; + /* Insert entries in canonical order: other orders seem + to confuse Solaris VxFS. */ + acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ + acl2->a_entries[1] = acl->a_entries[1]; /* ACL_GROUP_OBJ */ + acl2->a_entries[2] = acl->a_entries[1]; /* ACL_MASK */ + acl2->a_entries[2].e_tag = ACL_MASK; + acl2->a_entries[3] = acl->a_entries[2]; /* ACL_OTHER */ + nfsacl_desc.acl = acl2; + } err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); + if (acl2) + posix_acl_release(acl2); if (!err) err = 8 + nfsacl_desc.desc.elem_size * nfsacl_desc.desc.array_len; -- cgit v0.10.2 From 1bef40032992320dd25a266fc166bfb8fa3f2f59 Mon Sep 17 00:00:00 2001 From: Suzuki Date: Tue, 11 Oct 2005 08:29:06 -0700 Subject: [PATCH] madvise: Avoid returning error code -EBADF for anonymous mappings Revert this recent correctness change: Douglas Crosher reported that it broke an existing application, and that madvise() works without error on anonymous mappings on Solaris. This means that madvise() will remain non-standards-compliant: we should return -EBADF for all requests against non-file-backed vma's, but Linux only does this for MADV_WILLNEED requests. Signed-off-by: Suzuki K P Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/madvise.c b/mm/madvise.c index 4454936..20e075d 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -83,6 +83,9 @@ static long madvise_willneed(struct vm_area_struct * vma, { struct file *file = vma->vm_file; + if (!file) + return -EBADF; + if (file->f_mapping->a_ops->get_xip_page) { /* no bad return value, but ignore advice */ return 0; @@ -141,11 +144,7 @@ static long madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, unsigned long start, unsigned long end, int behavior) { - struct file *filp = vma->vm_file; - long error = -EBADF; - - if (!filp) - goto out; + long error; switch (behavior) { case MADV_NORMAL: @@ -166,8 +165,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, error = -EINVAL; break; } - -out: return error; } -- cgit v0.10.2 From a0c111c631e7ab4abd68920debd44259160812ef Mon Sep 17 00:00:00 2001 From: Paolo Galtieri Date: Tue, 11 Oct 2005 08:29:07 -0700 Subject: [PATCH] ppc highmem fix I've noticed that the calculations for seg_size and nr_segs in __dma_sync_page_highmem() (arch/ppc/kernel/dma-mapping.c) are wrong. The incorrect calculations can result in either an oops or a panic when running fsck depending on the size of the partition. The problem with the seg_size calculation is that it can result in a negative number if size is offset > size. The problem with the nr_segs caculation is returns the wrong number of segments, e.g. it returns 1 when size is 200 and offset is 4095, when it should return 2 or more. Acked-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index b566d98..8edee80 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c @@ -401,10 +401,10 @@ EXPORT_SYMBOL(__dma_sync); static inline void __dma_sync_page_highmem(struct page *page, unsigned long offset, size_t size, int direction) { - size_t seg_size = min((size_t)PAGE_SIZE, size) - offset; + size_t seg_size = min((size_t)(PAGE_SIZE - offset), size); size_t cur_size = seg_size; unsigned long flags, start, seg_offset = offset; - int nr_segs = PAGE_ALIGN(size + (PAGE_SIZE - offset))/PAGE_SIZE; + int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE; int seg_nr = 0; local_irq_save(flags); -- cgit v0.10.2 From 6de505173e24e76bb33a2595312e0c2b44d49e58 Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Tue, 11 Oct 2005 08:29:08 -0700 Subject: [PATCH] binfmt_elf bss padding fix Nir Tzachar points out that if an ELF file specifies a zero-length bss at a whacky address, we cannot load that binary because padzero() tries to zero out the end of the page at the whacky address, and that may not be writeable. See also http://bugzilla.kernel.org/show_bug.cgi?id=5411 So teach load_elf_binary() to skip the bss settng altogether if the elf file has a zero-length bss segment. Cc: Roland McGrath Cc: Daniel Jacobowitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7976a23..d4b1557 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -905,7 +905,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) send_sig(SIGKILL, current, 0); goto out_free_dentry; } - if (padzero(elf_bss)) { + if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { send_sig(SIGSEGV, current, 0); retval = -EFAULT; /* Nobody gets to see this, but.. */ goto out_free_dentry; -- cgit v0.10.2 From 9de11aab1c8fd87da7e1fb435ce0ff26bacd7909 Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Tue, 11 Oct 2005 08:29:09 -0700 Subject: [PATCH] m32r: trap handler code for illegal traps This patch prevents illegal traps from causing m32r kernel's infinite loop execution. Signed-off-by: Naoto Sugai Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index dddbf6b..85920fb 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -681,6 +681,15 @@ ENTRY(debug_trap) bl do_debug_trap bra error_code +ENTRY(ill_trap) + /* void ill_trap(void) */ + SWITCH_TO_KERNEL_STACK + SAVE_ALL + ldi r1, #0 ; error_code ; FIXME + mv r0, sp ; pt_regs + bl do_ill_trap + bra error_code + /* Cache flushing handler */ ENTRY(cache_flushing_handler) diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c index 0192227..5fe8ed6 100644 --- a/arch/m32r/kernel/traps.c +++ b/arch/m32r/kernel/traps.c @@ -5,8 +5,6 @@ * Hitoshi Yamamoto */ -/* $Id$ */ - /* * 'traps.c' handles hardware traps and faults after we have saved some * state in 'entry.S'. @@ -35,6 +33,7 @@ asmlinkage void ei_handler(void); asmlinkage void rie_handler(void); asmlinkage void debug_trap(void); asmlinkage void cache_flushing_handler(void); +asmlinkage void ill_trap(void); #ifdef CONFIG_SMP extern void smp_reschedule_interrupt(void); @@ -77,22 +76,22 @@ void set_eit_vector_entries(void) eit_vector[5] = BRA_INSN(default_eit_handler, 5); eit_vector[8] = BRA_INSN(rie_handler, 8); eit_vector[12] = BRA_INSN(alignment_check, 12); - eit_vector[16] = 0xff000000UL; + eit_vector[16] = BRA_INSN(ill_trap, 16); eit_vector[17] = BRA_INSN(debug_trap, 17); eit_vector[18] = BRA_INSN(system_call, 18); - eit_vector[19] = 0xff000000UL; - eit_vector[20] = 0xff000000UL; - eit_vector[21] = 0xff000000UL; - eit_vector[22] = 0xff000000UL; - eit_vector[23] = 0xff000000UL; - eit_vector[24] = 0xff000000UL; - eit_vector[25] = 0xff000000UL; - eit_vector[26] = 0xff000000UL; - eit_vector[27] = 0xff000000UL; + eit_vector[19] = BRA_INSN(ill_trap, 19); + eit_vector[20] = BRA_INSN(ill_trap, 20); + eit_vector[21] = BRA_INSN(ill_trap, 21); + eit_vector[22] = BRA_INSN(ill_trap, 22); + eit_vector[23] = BRA_INSN(ill_trap, 23); + eit_vector[24] = BRA_INSN(ill_trap, 24); + eit_vector[25] = BRA_INSN(ill_trap, 25); + eit_vector[26] = BRA_INSN(ill_trap, 26); + eit_vector[27] = BRA_INSN(ill_trap, 27); eit_vector[28] = BRA_INSN(cache_flushing_handler, 28); - eit_vector[29] = 0xff000000UL; - eit_vector[30] = 0xff000000UL; - eit_vector[31] = 0xff000000UL; + eit_vector[29] = BRA_INSN(ill_trap, 29); + eit_vector[30] = BRA_INSN(ill_trap, 30); + eit_vector[31] = BRA_INSN(ill_trap, 31); eit_vector[32] = BRA_INSN(ei_handler, 32); eit_vector[64] = BRA_INSN(pie_handler, 64); #ifdef CONFIG_MMU @@ -286,7 +285,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap) DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc) -DO_ERROR_INFO(0x100, SIGILL, "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc) +DO_ERROR_INFO(0x100, SIGILL, "privileged instruction", pie_handler, ILL_PRVOPC, regs->bpc) +DO_ERROR_INFO(-1, SIGILL, "illegal trap", ill_trap, ILL_ILLTRP, regs->bpc) extern int handle_unaligned_access(unsigned long, struct pt_regs *); @@ -329,4 +329,3 @@ asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code) set_fs(oldfs); } } - -- cgit v0.10.2 From d3089792f6ee38cdc9e254a7cb2f8c8d7f38c20d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 11 Oct 2005 09:28:24 -0700 Subject: [PATCH] V4L: Enable s-video input on DViCO FusionHDTV5 Lite * bttv-cards.c: - Enable S-Video input on DViCO FusionHDTV5 Lite Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 6c33280..0881a17 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -2393,10 +2393,10 @@ struct tvcard bttv_tvcards[] = { .tuner = 0, .tuner_type = TUNER_LG_TDVS_H062F, .tuner_addr = ADDR_UNSET, - .video_inputs = 2, + .video_inputs = 3, .audio_inputs = 1, .svhs = 2, - .muxsel = { 2, 3 }, + .muxsel = { 2, 3, 1 }, .gpiomask = 0x00e00007, .audiomux = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 }, .no_msp34xx = 1, -- cgit v0.10.2 From 9149ccfa3571eaa4a4b444777d67fc4ed3ebcf27 Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Tue, 11 Oct 2005 09:28:24 -0700 Subject: [PATCH] ppc64: Add R_PPC64_TOC16 module reloc Newer gcc's are generating this relocation, so the module loader needs to handle it. Signed-off-by: Peter Bergner Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c index c683bf8..928b858 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/ppc64/kernel/module.c @@ -341,6 +341,19 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, *(unsigned long *)location = my_r2(sechdrs, me); break; + case R_PPC64_TOC16: + /* Subtact TOC pointer */ + value -= my_r2(sechdrs, me); + if (value + 0x8000 > 0xffff) { + printk("%s: bad TOC16 relocation (%lu)\n", + me->name, value); + return -ENOEXEC; + } + *((uint16_t *) location) + = (*((uint16_t *) location) & ~0xffff) + | (value & 0xffff); + break; + case R_PPC64_TOC16_DS: /* Subtact TOC pointer */ value -= my_r2(sechdrs, me); -- cgit v0.10.2 From f5154a98a1931641f0448f6512294a15279110d7 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 11 Oct 2005 19:16:26 +0100 Subject: [PATCH] Don't map the same page too much Refuse to install a page into a mapping if the mapping count is already ridiculously large. You probably cannot trigger this on 32-bit architectures, but on a 64-bit setup we should protect against it. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds diff --git a/mm/fremap.c b/mm/fremap.c index 3235fb7..ab23a06 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -89,6 +89,9 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma, size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (!page->mapping || page->index >= size) goto err_unlock; + err = -ENOMEM; + if (page_mapcount(page) > INT_MAX/2) + goto err_unlock; zap_pte(mm, vma, addr, pte); -- cgit v0.10.2 From b1b510aa284af1908d5d369d52f7dae16aaabd71 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 11 Oct 2005 15:45:16 -0700 Subject: [SPARC64]: Fix net booting on Ultra5 We were not doing alignment properly when remapping the kernel image. What we want is a 4MB aligned physical address to map at KERNBASE. Mistakedly we were 4MB aligning the virtual address where the kernel initially sits, that's wrong. Instead, we should PAGE align the virtual address, then 4MB align the physical address result the prom gives to us. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index f1dcdf8..4c942f7 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -191,8 +191,9 @@ prom_boot_mapping_phys_low: stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5 stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate" stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache - srlx %l0, 22, %l3 - sllx %l3, 22, %l3 + /* PAGE align */ + srlx %l0, 13, %l3 + sllx %l3, 13, %l3 stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC stx %g0, [%sp + 2047 + 128 + 0x30] ! res1 stx %g0, [%sp + 2047 + 128 + 0x38] ! res2 @@ -211,6 +212,9 @@ prom_boot_mapping_phys_low: ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high stx %l2, [%l4 + 0x0] ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low + /* 4MB align */ + srlx %l3, 22, %l3 + sllx %l3, 22, %l3 stx %l3, [%l4 + 0x8] /* Leave service as-is, "call-method" */ -- cgit v0.10.2 From 91acb21f084aa244f26839406ae7ed8aa3668058 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 10 Oct 2005 23:10:32 -0400 Subject: [PATCH] uml: revert block driver use of host AIO The patch to use host AIO support that I submitted early after 2.6.13 exposed some problems in the block driver. I have fixes for these, but am not comfortable putting them into 2.6.14 at this late date. So, this patch reverts the use of host AIO. I will resubmit the original patch, plus fixes to the driver after 2.6.14 in order to get a reasonable amount of testing before they're exposed to the general public. Signed-off-by: Jeff Dike Signed-off-by: Linus Torvalds diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 783e18c..de17d4c 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -13,7 +13,7 @@ mcast-objs := mcast_kern.o mcast_user.o net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o -ubd-objs := ubd_kern.o +ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o harddog-objs := harddog_kern.o harddog_user.o diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index e77a38d..f731343 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -35,7 +35,6 @@ #include "linux/blkpg.h" #include "linux/genhd.h" #include "linux/spinlock.h" -#include "asm/atomic.h" #include "asm/segment.h" #include "asm/uaccess.h" #include "asm/irq.h" @@ -54,21 +53,20 @@ #include "mem.h" #include "mem_kern.h" #include "cow.h" -#include "aio.h" enum ubd_req { UBD_READ, UBD_WRITE }; struct io_thread_req { - enum aio_type op; + enum ubd_req op; int fds[2]; unsigned long offsets[2]; unsigned long long offset; unsigned long length; char *buffer; int sectorsize; - int bitmap_offset; - long bitmap_start; - long bitmap_end; + unsigned long sector_mask; + unsigned long long cow_offset; + unsigned long bitmap_words[2]; int error; }; @@ -82,31 +80,28 @@ extern int create_cow_file(char *cow_file, char *backing_file, unsigned long *bitmap_len_out, int *data_offset_out); extern int read_cow_bitmap(int fd, void *buf, int offset, int len); -extern void do_io(struct io_thread_req *req, struct request *r, - unsigned long *bitmap); +extern void do_io(struct io_thread_req *req); -static inline int ubd_test_bit(__u64 bit, void *data) +static inline int ubd_test_bit(__u64 bit, unsigned char *data) { - unsigned char *buffer = data; __u64 n; int bits, off; - bits = sizeof(buffer[0]) * 8; + bits = sizeof(data[0]) * 8; n = bit / bits; off = bit % bits; - return((buffer[n] & (1 << off)) != 0); + return((data[n] & (1 << off)) != 0); } -static inline void ubd_set_bit(__u64 bit, void *data) +static inline void ubd_set_bit(__u64 bit, unsigned char *data) { - unsigned char *buffer = data; __u64 n; int bits, off; - bits = sizeof(buffer[0]) * 8; + bits = sizeof(data[0]) * 8; n = bit / bits; off = bit % bits; - buffer[n] |= (1 << off); + data[n] |= (1 << off); } /*End stuff from ubd_user.h*/ @@ -115,6 +110,8 @@ static inline void ubd_set_bit(__u64 bit, void *data) static DEFINE_SPINLOCK(ubd_io_lock); static DEFINE_SPINLOCK(ubd_lock); +static void (*do_ubd)(void); + static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); static int ubd_ioctl(struct inode * inode, struct file * file, @@ -161,8 +158,6 @@ struct cow { int data_offset; }; -#define MAX_SG 64 - struct ubd { char *file; int count; @@ -173,7 +168,6 @@ struct ubd { int no_cow; struct cow cow; struct platform_device pdev; - struct scatterlist sg[MAX_SG]; }; #define DEFAULT_COW { \ @@ -466,114 +460,81 @@ __uml_help(fakehd, ); static void do_ubd_request(request_queue_t * q); -static int in_ubd; + +/* Only changed by ubd_init, which is an initcall. */ +int thread_fd = -1; /* Changed by ubd_handler, which is serialized because interrupts only * happen on CPU 0. */ int intr_count = 0; -static void ubd_end_request(struct request *req, int bytes, int uptodate) +/* call ubd_finish if you need to serialize */ +static void __ubd_finish(struct request *req, int error) { - if (!end_that_request_first(req, uptodate, bytes >> 9)) { - add_disk_randomness(req->rq_disk); - end_that_request_last(req); + int nsect; + + if(error){ + end_request(req, 0); + return; } + nsect = req->current_nr_sectors; + req->sector += nsect; + req->buffer += nsect << 9; + req->errors = 0; + req->nr_sectors -= nsect; + req->current_nr_sectors = 0; + end_request(req, 1); } -/* call ubd_finish if you need to serialize */ -static void __ubd_finish(struct request *req, int bytes) +static inline void ubd_finish(struct request *req, int error) { - if(bytes < 0){ - ubd_end_request(req, 0, 0); - return; - } - - ubd_end_request(req, bytes, 1); + spin_lock(&ubd_io_lock); + __ubd_finish(req, error); + spin_unlock(&ubd_io_lock); } -static inline void ubd_finish(struct request *req, int bytes) +/* Called without ubd_io_lock held */ +static void ubd_handler(void) { - spin_lock(&ubd_io_lock); - __ubd_finish(req, bytes); - spin_unlock(&ubd_io_lock); + struct io_thread_req req; + struct request *rq = elv_next_request(ubd_queue); + int n; + + do_ubd = NULL; + intr_count++; + n = os_read_file(thread_fd, &req, sizeof(req)); + if(n != sizeof(req)){ + printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " + "err = %d\n", os_getpid(), -n); + spin_lock(&ubd_io_lock); + end_request(rq, 0); + spin_unlock(&ubd_io_lock); + return; + } + + ubd_finish(rq, req.error); + reactivate_fd(thread_fd, UBD_IRQ); + do_ubd_request(ubd_queue); } -struct bitmap_io { - atomic_t count; - struct aio_context aio; -}; - -struct ubd_aio { - struct aio_context aio; - struct request *req; - int len; - struct bitmap_io *bitmap; - void *bitmap_buf; -}; - -static int ubd_reply_fd = -1; - static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) { - struct aio_thread_reply reply; - struct ubd_aio *aio; - struct request *req; - int err, n, fd = (int) (long) dev; - - while(1){ - err = os_read_file(fd, &reply, sizeof(reply)); - if(err == -EAGAIN) - break; - if(err < 0){ - printk("ubd_aio_handler - read returned err %d\n", - -err); - break; - } - - aio = container_of(reply.data, struct ubd_aio, aio); - n = reply.err; - - if(n == 0){ - req = aio->req; - req->nr_sectors -= aio->len >> 9; - - if((aio->bitmap != NULL) && - (atomic_dec_and_test(&aio->bitmap->count))){ - aio->aio = aio->bitmap->aio; - aio->len = 0; - kfree(aio->bitmap); - aio->bitmap = NULL; - submit_aio(&aio->aio); - } - else { - if((req->nr_sectors == 0) && - (aio->bitmap == NULL)){ - int len = req->hard_nr_sectors << 9; - ubd_finish(req, len); - } - - if(aio->bitmap_buf != NULL) - kfree(aio->bitmap_buf); - kfree(aio); - } - } - else if(n < 0){ - ubd_finish(aio->req, n); - if(aio->bitmap != NULL) - kfree(aio->bitmap); - if(aio->bitmap_buf != NULL) - kfree(aio->bitmap_buf); - kfree(aio); - } - } - reactivate_fd(fd, UBD_IRQ); + ubd_handler(); + return(IRQ_HANDLED); +} - do_ubd_request(ubd_queue); +/* Only changed by ubd_init, which is an initcall. */ +static int io_pid = -1; - return(IRQ_HANDLED); +void kill_io_thread(void) +{ + if(io_pid != -1) + os_kill_process(io_pid, 1); } +__uml_exitcall(kill_io_thread); + static int ubd_file_size(struct ubd *dev, __u64 *size_out) { char *file; @@ -608,7 +569,7 @@ static int ubd_open_dev(struct ubd *dev) &dev->cow.data_offset, create_ptr); if((dev->fd == -ENOENT) && create_cow){ - dev->fd = create_cow_file(dev->file, dev->cow.file, + dev->fd = create_cow_file(dev->file, dev->cow.file, dev->openflags, 1 << 9, PAGE_SIZE, &dev->cow.bitmap_offset, &dev->cow.bitmap_len, @@ -870,10 +831,6 @@ int ubd_init(void) { int i; - ubd_reply_fd = init_aio_irq(UBD_IRQ, "ubd", ubd_intr); - if(ubd_reply_fd < 0) - printk("Setting up ubd AIO failed, err = %d\n", ubd_reply_fd); - devfs_mk_dir("ubd"); if (register_blkdev(MAJOR_NR, "ubd")) return -1; @@ -884,7 +841,6 @@ int ubd_init(void) return -1; } - blk_queue_max_hw_segments(ubd_queue, MAX_SG); if (fake_major != MAJOR_NR) { char name[sizeof("ubd_nnn\0")]; @@ -896,12 +852,40 @@ int ubd_init(void) driver_register(&ubd_driver); for (i = 0; i < MAX_DEV; i++) ubd_add(i); - return 0; } late_initcall(ubd_init); +int ubd_driver_init(void){ + unsigned long stack; + int err; + + /* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/ + if(global_openflags.s){ + printk(KERN_INFO "ubd: Synchronous mode\n"); + /* Letting ubd=sync be like using ubd#s= instead of ubd#= is + * enough. So use anyway the io thread. */ + } + stack = alloc_stack(0, 0); + io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), + &thread_fd); + if(io_pid < 0){ + printk(KERN_ERR + "ubd : Failed to start I/O thread (errno = %d) - " + "falling back to synchronous I/O\n", -io_pid); + io_pid = -1; + return(0); + } + err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, + SA_INTERRUPT, "ubd", ubd_dev); + if(err != 0) + printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); + return(err); +} + +device_initcall(ubd_driver_init); + static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; @@ -939,55 +923,105 @@ static int ubd_release(struct inode * inode, struct file * file) return(0); } -static void cowify_bitmap(struct io_thread_req *req, unsigned long *bitmap) +static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, + __u64 *cow_offset, unsigned long *bitmap, + __u64 bitmap_offset, unsigned long *bitmap_words, + __u64 bitmap_len) { - __u64 sector = req->offset / req->sectorsize; - int i; + __u64 sector = io_offset >> 9; + int i, update_bitmap = 0; + + for(i = 0; i < length >> 9; i++){ + if(cow_mask != NULL) + ubd_set_bit(i, (unsigned char *) cow_mask); + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) + continue; - for(i = 0; i < req->length / req->sectorsize; i++){ - if(ubd_test_bit(sector + i, bitmap)) - continue; + update_bitmap = 1; + ubd_set_bit(sector + i, (unsigned char *) bitmap); + } + + if(!update_bitmap) + return; - if(req->bitmap_start == -1) - req->bitmap_start = sector + i; - req->bitmap_end = sector + i + 1; + *cow_offset = sector / (sizeof(unsigned long) * 8); - ubd_set_bit(sector + i, bitmap); - } + /* This takes care of the case where we're exactly at the end of the + * device, and *cow_offset + 1 is off the end. So, just back it up + * by one word. Thanks to Lynn Kerby for the fix and James McMechan + * for the original diagnosis. + */ + if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / + sizeof(unsigned long) - 1)) + (*cow_offset)--; + + bitmap_words[0] = bitmap[*cow_offset]; + bitmap_words[1] = bitmap[*cow_offset + 1]; + + *cow_offset *= sizeof(unsigned long); + *cow_offset += bitmap_offset; +} + +static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, + __u64 bitmap_offset, __u64 bitmap_len) +{ + __u64 sector = req->offset >> 9; + int i; + + if(req->length > (sizeof(req->sector_mask) * 8) << 9) + panic("Operation too long"); + + if(req->op == UBD_READ) { + for(i = 0; i < req->length >> 9; i++){ + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) + ubd_set_bit(i, (unsigned char *) + &req->sector_mask); + } + } + else cowify_bitmap(req->offset, req->length, &req->sector_mask, + &req->cow_offset, bitmap, bitmap_offset, + req->bitmap_words, bitmap_len); } /* Called with ubd_io_lock held */ -static int prepare_request(struct request *req, struct io_thread_req *io_req, - unsigned long long offset, int page_offset, - int len, struct page *page) +static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; struct ubd *dev = disk->private_data; + __u64 offset; + int len; + + if(req->rq_status == RQ_INACTIVE) return(1); /* This should be impossible now */ if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); - ubd_end_request(req, 0, 0); + end_request(req, 0); return(1); } + offset = ((__u64) req->sector) << 9; + len = req->current_nr_sectors << 9; + io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; io_req->fds[1] = dev->fd; + io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; io_req->error = 0; - io_req->op = (rq_data_dir(req) == READ) ? AIO_READ : AIO_WRITE; + io_req->sector_mask = 0; + + io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; io_req->offsets[1] = dev->cow.data_offset; - io_req->buffer = page_address(page) + page_offset; + io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - io_req->bitmap_offset = dev->cow.bitmap_offset; - io_req->bitmap_start = -1; - io_req->bitmap_end = -1; - if((dev->cow.file != NULL) && (io_req->op == UBD_WRITE)) - cowify_bitmap(io_req, dev->cow.bitmap); + if(dev->cow.file != NULL) + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); + return(0); } @@ -996,36 +1030,30 @@ static void do_ubd_request(request_queue_t *q) { struct io_thread_req io_req; struct request *req; - __u64 sector; - int err; - - if(in_ubd) - return; - in_ubd = 1; - while((req = elv_next_request(q)) != NULL){ - struct gendisk *disk = req->rq_disk; - struct ubd *dev = disk->private_data; - int n, i; - - blkdev_dequeue_request(req); - - sector = req->sector; - n = blk_rq_map_sg(q, req, dev->sg); - - for(i = 0; i < n; i++){ - struct scatterlist *sg = &dev->sg[i]; - - err = prepare_request(req, &io_req, sector << 9, - sg->offset, sg->length, - sg->page); - if(err) - continue; - - sector += sg->length >> 9; - do_io(&io_req, req, dev->cow.bitmap); + int err, n; + + if(thread_fd == -1){ + while((req = elv_next_request(q)) != NULL){ + err = prepare_request(req, &io_req); + if(!err){ + do_io(&io_req); + __ubd_finish(req, io_req.error); + } + } + } + else { + if(do_ubd || (req = elv_next_request(q)) == NULL) + return; + err = prepare_request(req, &io_req); + if(!err){ + do_ubd = ubd_handler; + n = os_write_file(thread_fd, (char *) &io_req, + sizeof(io_req)); + if(n != sizeof(io_req)) + printk("write to io thread failed, " + "errno = %d\n", -n); } } - in_ubd = 0; } static int ubd_ioctl(struct inode * inode, struct file * file, @@ -1241,95 +1269,131 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, return(err); } -void do_io(struct io_thread_req *req, struct request *r, unsigned long *bitmap) +static int update_bitmap(struct io_thread_req *req) { - struct ubd_aio *aio; - struct bitmap_io *bitmap_io = NULL; - char *buf; - void *bitmap_buf = NULL; - unsigned long len, sector; - int nsectors, start, end, bit, err; - __u64 off; - - if(req->bitmap_start != -1){ - /* Round up to the nearest word */ - int round = sizeof(unsigned long); - len = (req->bitmap_end - req->bitmap_start + - round * 8 - 1) / (round * 8); - len *= round; - - off = req->bitmap_start / (8 * round); - off *= round; - - bitmap_io = kmalloc(sizeof(*bitmap_io), GFP_KERNEL); - if(bitmap_io == NULL){ - printk("Failed to kmalloc bitmap IO\n"); - req->error = 1; - return; - } + int n; - bitmap_buf = kmalloc(len, GFP_KERNEL); - if(bitmap_buf == NULL){ - printk("do_io : kmalloc of bitmap chunk " - "failed\n"); - kfree(bitmap_io); - req->error = 1; - return; - } - memcpy(bitmap_buf, &bitmap[off / sizeof(bitmap[0])], len); - - *bitmap_io = ((struct bitmap_io) - { .count = ATOMIC_INIT(0), - .aio = INIT_AIO(AIO_WRITE, req->fds[1], - bitmap_buf, len, - req->bitmap_offset + off, - ubd_reply_fd) } ); - } + if(req->cow_offset == -1) + return(0); - nsectors = req->length / req->sectorsize; - start = 0; - end = nsectors; - bit = 0; - do { - if(bitmap != NULL){ - sector = req->offset / req->sectorsize; - bit = ubd_test_bit(sector + start, bitmap); - end = start; - while((end < nsectors) && - (ubd_test_bit(sector + end, bitmap) == bit)) - end++; - } + n = os_seek_file(req->fds[1], req->cow_offset); + if(n < 0){ + printk("do_io - bitmap lseek failed : err = %d\n", -n); + return(1); + } - off = req->offsets[bit] + req->offset + - start * req->sectorsize; - len = (end - start) * req->sectorsize; - buf = &req->buffer[start * req->sectorsize]; + n = os_write_file(req->fds[1], &req->bitmap_words, + sizeof(req->bitmap_words)); + if(n != sizeof(req->bitmap_words)){ + printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, + req->fds[1]); + return(1); + } - aio = kmalloc(sizeof(*aio), GFP_KERNEL); - if(aio == NULL){ - req->error = 1; - return; - } + return(0); +} - *aio = ((struct ubd_aio) - { .aio = INIT_AIO(req->op, req->fds[bit], buf, - len, off, ubd_reply_fd), - .len = len, - .req = r, - .bitmap = bitmap_io, - .bitmap_buf = bitmap_buf }); - - if(aio->bitmap != NULL) - atomic_inc(&aio->bitmap->count); - - err = submit_aio(&aio->aio); - if(err){ - printk("do_io - submit_aio failed, " - "err = %d\n", err); - req->error = 1; - return; - } +void do_io(struct io_thread_req *req) +{ + char *buf; + unsigned long len; + int n, nsectors, start, end, bit; + int err; + __u64 off; + + nsectors = req->length / req->sectorsize; + start = 0; + do { + bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask); + end = start; + while((end < nsectors) && + (ubd_test_bit(end, (unsigned char *) + &req->sector_mask) == bit)) + end++; + + off = req->offset + req->offsets[bit] + + start * req->sectorsize; + len = (end - start) * req->sectorsize; + buf = &req->buffer[start * req->sectorsize]; + + err = os_seek_file(req->fds[bit], off); + if(err < 0){ + printk("do_io - lseek failed : err = %d\n", -err); + req->error = 1; + return; + } + if(req->op == UBD_READ){ + n = 0; + do { + buf = &buf[n]; + len -= n; + n = os_read_file(req->fds[bit], buf, len); + if (n < 0) { + printk("do_io - read failed, err = %d " + "fd = %d\n", -n, req->fds[bit]); + req->error = 1; + return; + } + } while((n < len) && (n != 0)); + if (n < len) memset(&buf[n], 0, len - n); + } else { + n = os_write_file(req->fds[bit], buf, len); + if(n != len){ + printk("do_io - write failed err = %d " + "fd = %d\n", -n, req->fds[bit]); + req->error = 1; + return; + } + } + + start = end; + } while(start < nsectors); - start = end; - } while(start < nsectors); + req->error = update_bitmap(req); } + +/* Changed in start_io_thread, which is serialized by being called only + * from ubd_init, which is an initcall. + */ +int kernel_fd = -1; + +/* Only changed by the io thread */ +int io_count = 0; + +int io_thread(void *arg) +{ + struct io_thread_req req; + int n; + + ignore_sigwinch_sig(); + while(1){ + n = os_read_file(kernel_fd, &req, sizeof(req)); + if(n != sizeof(req)){ + if(n < 0) + printk("io_thread - read failed, fd = %d, " + "err = %d\n", kernel_fd, -n); + else { + printk("io_thread - short read, fd = %d, " + "length = %d\n", kernel_fd, n); + } + continue; + } + io_count++; + do_io(&req); + n = os_write_file(kernel_fd, &req, sizeof(req)); + if(n != sizeof(req)) + printk("io_thread - write failed, fd = %d, err = %d\n", + kernel_fd, -n); + } +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c new file mode 100644 index 0000000..b94d2bc4f --- /dev/null +++ b/arch/um/drivers/ubd_user.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "asm/types.h" +#include "user_util.h" +#include "kern_util.h" +#include "user.h" +#include "ubd_user.h" +#include "os.h" +#include "cow.h" + +#include +#include + +void ignore_sigwinch_sig(void) +{ + signal(SIGWINCH, SIG_IGN); +} + +int start_io_thread(unsigned long sp, int *fd_out) +{ + int pid, fds[2], err; + + err = os_pipe(fds, 1, 1); + if(err < 0){ + printk("start_io_thread - os_pipe failed, err = %d\n", -err); + goto out; + } + + kernel_fd = fds[0]; + *fd_out = fds[1]; + + pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, + NULL); + if(pid < 0){ + printk("start_io_thread - clone failed : errno = %d\n", errno); + err = -errno; + goto out_close; + } + + return(pid); + + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + kernel_fd = -1; + *fd_out = -1; + out: + return(err); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/include/aio.h b/arch/um/include/aio.h index 83f1687..423bae91 100644 --- a/arch/um/include/aio.h +++ b/arch/um/include/aio.h @@ -14,27 +14,15 @@ struct aio_thread_reply { }; struct aio_context { - enum aio_type type; - int fd; - void *data; - int len; - unsigned long long offset; int reply_fd; struct aio_context *next; }; -#define INIT_AIO(aio_type, aio_fd, aio_data, aio_len, aio_offset, \ - aio_reply_fd) \ - { .type = aio_type, \ - .fd = aio_fd, \ - .data = aio_data, \ - .len = aio_len, \ - .offset = aio_offset, \ - .reply_fd = aio_reply_fd } - #define INIT_AIO_CONTEXT { .reply_fd = -1, \ .next = NULL } -extern int submit_aio(struct aio_context *aio); +extern int submit_aio(enum aio_type type, int fd, char *buf, int len, + unsigned long long offset, int reply_fd, + struct aio_context *aio); #endif diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index f6e6402..41cfb09 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -17,31 +16,18 @@ #include "user.h" #include "mode.h" +struct aio_thread_req { + enum aio_type type; + int io_fd; + unsigned long long offset; + char *buf; + int len; + struct aio_context *aio; +}; + static int aio_req_fd_r = -1; static int aio_req_fd_w = -1; -static int update_aio(struct aio_context *aio, int res) -{ - if(res < 0) - aio->len = res; - else if((res == 0) && (aio->type == AIO_READ)){ - /* This is the EOF case - we have hit the end of the file - * and it ends in a partial block, so we fill the end of - * the block with zeros and claim success. - */ - memset(aio->data, 0, aio->len); - aio->len = 0; - } - else if(res > 0){ - aio->len -= res; - aio->data += res; - aio->offset += res; - return aio->len; - } - - return 0; -} - #if defined(HAVE_AIO_ABI) #include @@ -80,7 +66,8 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, * that it now backs the mmapped area. */ -static int do_aio(aio_context_t ctx, struct aio_context *aio) +static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, + int len, unsigned long long offset, struct aio_context *aio) { struct iocb iocb, *iocbp = &iocb; char c; @@ -88,39 +75,40 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio) iocb = ((struct iocb) { .aio_data = (unsigned long) aio, .aio_reqprio = 0, - .aio_fildes = aio->fd, - .aio_buf = (unsigned long) aio->data, - .aio_nbytes = aio->len, - .aio_offset = aio->offset, + .aio_fildes = fd, + .aio_buf = (unsigned long) buf, + .aio_nbytes = len, + .aio_offset = offset, .aio_reserved1 = 0, .aio_reserved2 = 0, .aio_reserved3 = 0 }); - switch(aio->type){ + switch(type){ case AIO_READ: iocb.aio_lio_opcode = IOCB_CMD_PREAD; + err = io_submit(ctx, 1, &iocbp); break; case AIO_WRITE: iocb.aio_lio_opcode = IOCB_CMD_PWRITE; + err = io_submit(ctx, 1, &iocbp); break; case AIO_MMAP: iocb.aio_lio_opcode = IOCB_CMD_PREAD; iocb.aio_buf = (unsigned long) &c; iocb.aio_nbytes = sizeof(c); + err = io_submit(ctx, 1, &iocbp); break; default: - printk("Bogus op in do_aio - %d\n", aio->type); + printk("Bogus op in do_aio - %d\n", type); err = -EINVAL; - goto out; + break; } - err = io_submit(ctx, 1, &iocbp); if(err > 0) err = 0; else err = -errno; - out: return err; } @@ -129,9 +117,8 @@ static aio_context_t ctx = 0; static int aio_thread(void *arg) { struct aio_thread_reply reply; - struct aio_context *aio; struct io_event event; - int err, n; + int err, n, reply_fd; signal(SIGWINCH, SIG_IGN); @@ -144,22 +131,14 @@ static int aio_thread(void *arg) "errno = %d\n", errno); } else { - /* This is safe as we've just a pointer here. */ - aio = (struct aio_context *) (long) event.data; - if(update_aio(aio, event.res)){ - do_aio(ctx, aio); - continue; - } - reply = ((struct aio_thread_reply) - { .data = aio, - .err = aio->len }); - err = os_write_file(aio->reply_fd, &reply, - sizeof(reply)); + { .data = (void *) (long) event.data, + .err = event.res }); + reply_fd = ((struct aio_context *) reply.data)->reply_fd; + err = os_write_file(reply_fd, &reply, sizeof(reply)); if(err != sizeof(reply)) - printk("aio_thread - write failed, " - "fd = %d, err = %d\n", aio->reply_fd, - -err); + printk("aio_thread - write failed, fd = %d, " + "err = %d\n", aio_req_fd_r, -err); } } return 0; @@ -167,35 +146,35 @@ static int aio_thread(void *arg) #endif -static int do_not_aio(struct aio_context *aio) +static int do_not_aio(struct aio_thread_req *req) { char c; int err; - switch(aio->type){ + switch(req->type){ case AIO_READ: - err = os_seek_file(aio->fd, aio->offset); + err = os_seek_file(req->io_fd, req->offset); if(err) goto out; - err = os_read_file(aio->fd, aio->data, aio->len); + err = os_read_file(req->io_fd, req->buf, req->len); break; case AIO_WRITE: - err = os_seek_file(aio->fd, aio->offset); + err = os_seek_file(req->io_fd, req->offset); if(err) goto out; - err = os_write_file(aio->fd, aio->data, aio->len); + err = os_write_file(req->io_fd, req->buf, req->len); break; case AIO_MMAP: - err = os_seek_file(aio->fd, aio->offset); + err = os_seek_file(req->io_fd, req->offset); if(err) goto out; - err = os_read_file(aio->fd, &c, sizeof(c)); + err = os_read_file(req->io_fd, &c, sizeof(c)); break; default: - printk("do_not_aio - bad request type : %d\n", aio->type); + printk("do_not_aio - bad request type : %d\n", req->type); err = -EINVAL; break; } @@ -206,14 +185,14 @@ static int do_not_aio(struct aio_context *aio) static int not_aio_thread(void *arg) { - struct aio_context *aio; + struct aio_thread_req req; struct aio_thread_reply reply; int err; signal(SIGWINCH, SIG_IGN); while(1){ - err = os_read_file(aio_req_fd_r, &aio, sizeof(aio)); - if(err != sizeof(aio)){ + err = os_read_file(aio_req_fd_r, &req, sizeof(req)); + if(err != sizeof(req)){ if(err < 0) printk("not_aio_thread - read failed, " "fd = %d, err = %d\n", aio_req_fd_r, @@ -224,34 +203,17 @@ static int not_aio_thread(void *arg) } continue; } - again: - err = do_not_aio(aio); - - if(update_aio(aio, err)) - goto again; - - reply = ((struct aio_thread_reply) { .data = aio, - .err = aio->len }); - err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); + err = do_not_aio(&req); + reply = ((struct aio_thread_reply) { .data = req.aio, + .err = err }); + err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); if(err != sizeof(reply)) printk("not_aio_thread - write failed, fd = %d, " "err = %d\n", aio_req_fd_r, -err); } } -static int submit_aio_24(struct aio_context *aio) -{ - int err; - - err = os_write_file(aio_req_fd_w, &aio, sizeof(aio)); - if(err == sizeof(aio)) - err = 0; - - return err; -} - static int aio_pid = -1; -static int (*submit_proc)(struct aio_context *aio); static int init_aio_24(void) { @@ -283,33 +245,11 @@ static int init_aio_24(void) #endif printk("2.6 host AIO support not used - falling back to I/O " "thread\n"); - - submit_proc = submit_aio_24; - return 0; } #ifdef HAVE_AIO_ABI #define DEFAULT_24_AIO 0 -static int submit_aio_26(struct aio_context *aio) -{ - struct aio_thread_reply reply; - int err; - - err = do_aio(ctx, aio); - if(err){ - reply = ((struct aio_thread_reply) { .data = aio, - .err = err }); - err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("submit_aio_26 - write failed, " - "fd = %d, err = %d\n", aio->reply_fd, -err); - else err = 0; - } - - return err; -} - static int init_aio_26(void) { unsigned long stack; @@ -330,22 +270,39 @@ static int init_aio_26(void) aio_pid = err; printk("Using 2.6 host AIO\n"); + return 0; +} + +static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, + unsigned long long offset, struct aio_context *aio) +{ + struct aio_thread_reply reply; + int err; - submit_proc = submit_aio_26; + err = do_aio(ctx, type, io_fd, buf, len, offset, aio); + if(err){ + reply = ((struct aio_thread_reply) { .data = aio, + .err = err }); + err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); + if(err != sizeof(reply)) + printk("submit_aio_26 - write failed, " + "fd = %d, err = %d\n", aio->reply_fd, -err); + else err = 0; + } - return 0; + return err; } #else #define DEFAULT_24_AIO 1 -static int submit_aio_26(struct aio_context *aio) +static int init_aio_26(void) { return -ENOSYS; } -static int init_aio_26(void) +static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, + unsigned long long offset, struct aio_context *aio) { - submit_proc = submit_aio_26; return -ENOSYS; } #endif @@ -412,7 +369,33 @@ static void exit_aio(void) __uml_exitcall(exit_aio); -int submit_aio(struct aio_context *aio) +static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, + unsigned long long offset, struct aio_context *aio) { - return (*submit_proc)(aio); + struct aio_thread_req req = { .type = type, + .io_fd = io_fd, + .offset = offset, + .buf = buf, + .len = len, + .aio = aio, + }; + int err; + + err = os_write_file(aio_req_fd_w, &req, sizeof(req)); + if(err == sizeof(req)) + err = 0; + + return err; +} + +int submit_aio(enum aio_type type, int io_fd, char *buf, int len, + unsigned long long offset, int reply_fd, + struct aio_context *aio) +{ + aio->reply_fd = reply_fd; + if(aio_24) + return submit_aio_24(type, io_fd, buf, len, offset, aio); + else { + return submit_aio_26(type, io_fd, buf, len, offset, aio); + } } -- cgit v0.10.2 From 9d624ea474a3ddf3a0702d9b47e428ce1f8488a6 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Tue, 11 Oct 2005 21:01:01 +0200 Subject: [PATCH] uml: compile-time fix recent patch Give an empty definition for clear_can_do_skas() when it is not needed. Thanks to Junichi Uekawa for reporting the breakage and providing a fix (I re-fixed it in an IMHO cleaner way). Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Linus Torvalds diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6f766e1..2e58e30 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -6,6 +6,7 @@ #ifndef __OS_H__ #define __OS_H__ +#include "uml-config.h" #include "asm/types.h" #include "../os/include/file.h" @@ -159,7 +160,11 @@ extern int can_do_skas(void); /* Make sure they are clear when running in TT mode. Required by * SEGV_MAYBE_FIXABLE */ +#ifdef UML_CONFIG_MODE_SKAS #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) +#else +#define clear_can_do_skas() do {} while (0) +#endif /* mem.c */ extern int create_mem_file(unsigned long len); -- cgit v0.10.2 From cbd27b8ced4b1888c93f69b4dd108a69ac4d733f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 12 Oct 2005 11:39:33 +1000 Subject: [PATCH] ppc32: Fix timekeeping Interestingly enough, ppc32 had broken timekeeping for ages... It worked, but probably drifted a bit more than could be explained by the actual bad precision of the timebase calibration. We discovered that recently when somebody figured out that the common code was using CLOCK_TICK_RATE to correct the timekeeing, and ppc32 had a completely bogus value for it. This patch turns it into something saner. Probably not as good as doing something based on the actual timebase frequency precision but I'll leave that sort of math to others. This at least makes it better for the common HZ values. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h index 51c5b31..c02d15a 100644 --- a/include/asm-powerpc/timex.h +++ b/include/asm-powerpc/timex.h @@ -10,7 +10,7 @@ #include #include -#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_RATE 1024000 /* Underlying HZ */ typedef unsigned long cycles_t; -- cgit v0.10.2 From d8e998c58a870770905495a1d45ebf7285b5b1c5 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 12 Oct 2005 14:22:50 +1000 Subject: [PATCH] ppc32: Tell userland about lack of standard TB Glibc is about to get some new high precision timer stuff that relies on the standard timebase of the PPC architecture. However, some (rare & old) CPUs do not have such timebase and it is a bit annoying to have your stuff just crash because you are running on the wrong CPU... This exposes to userland a CPU feature bit that tells that the current processor doesn't have a standard timebase. It's negative logic so that glibc will still "just work" on older kernels (it will just be unhappy on those old CPUs but that doesn't really matter as distro tend to update glibc & kernel at the same time). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 546e1ea..6b76cf5 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -91,7 +91,7 @@ struct cpu_spec cpu_specs[] = { .cpu_features = CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE, .cpu_user_features = COMMON_PPC | PPC_FEATURE_601_INSTR | - PPC_FEATURE_UNIFIED_CACHE, + PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB, .icache_bsize = 32, .dcache_bsize = 32, .cpu_setup = __setup_cpu_601 @@ -745,7 +745,8 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "403GCX", .cpu_features = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB, - .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB, .icache_bsize = 16, .dcache_bsize = 16, }, diff --git a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h index 41d8f84..e17c492 100644 --- a/include/asm-ppc/cputable.h +++ b/include/asm-ppc/cputable.h @@ -24,6 +24,7 @@ #define PPC_FEATURE_HAS_SPE 0x00800000 #define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 #define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 #ifdef __KERNEL__ -- cgit v0.10.2 From 60ac133aac9e07b94f2cb6bf571bf8aef69248c3 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 12 Oct 2005 19:51:24 +0100 Subject: [ARM] 2974/1: fix ARM710 swi bug workaround Patch from Nicolas Pitre Either no one is using an ARM710 with recent kernels, or all ARM710s still in use are not afflicted by this swi bug. Nevertheless, the code to work around the ARM710 swi bug is itself currently buggy since it uses r8 as a pointer to S_PC while in fact it holds the spsr content these days. Fix that, and simplify the code as well. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 81d450a..066597f 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -106,15 +106,10 @@ ENTRY(ret_from_fork) .endm .Larm700bug: - ldr r0, [sp, #S_PSR] @ Get calling cpsr - sub lr, lr, #4 - str lr, [r8] - msr spsr_cxsf, r0 ldmia sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 - ldr lr, [sp, #S_PC] @ Get PC add sp, sp, #S_FRAME_SIZE - movs pc, lr + subs pc, lr, #4 #else .macro arm710_bug_check, instr, temp .endm -- cgit v0.10.2 From 0eea3c0b6cb356bc8e515084f831cac7e3d5131c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 19:58:05 +0100 Subject: [ARM] 2975/1: S3C2410: time.c missing include of cpu.h Patch from Ben Dooks arch/arm/mach-s3c2410/time.c is missing include of cpu.h, causing the declaration of the timer struct (s3c24xx_timer) to be flagged as missing the declaration. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c index c0acfb2..8a00e3c 100644 --- a/arch/arm/mach-s3c2410/time.c +++ b/arch/arm/mach-s3c2410/time.c @@ -38,6 +38,7 @@ #include #include "clock.h" +#include "cpu.h" static unsigned long timer_startval; static unsigned long timer_usec_ticks; -- cgit v0.10.2 From 17efa644f624a521e4a6c6a4641d39d227a9b24a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 19:58:06 +0100 Subject: [ARM] 2976/1: S3C2410: add static to functions in serial driver Patch from Ben Dooks The s3c2410 serial driver is missing static declerations on several functions that are not exported, and have no need of being exported outside the driver Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index eff2158..52692aa 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1092,8 +1092,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, static int probe_index = 0; -int s3c24xx_serial_probe(struct device *_dev, - struct s3c24xx_uart_info *info) +static int s3c24xx_serial_probe(struct device *_dev, + struct s3c24xx_uart_info *info) { struct s3c24xx_uart_port *ourport; struct platform_device *dev = to_platform_device(_dev); @@ -1120,7 +1120,7 @@ int s3c24xx_serial_probe(struct device *_dev, return ret; } -int s3c24xx_serial_remove(struct device *_dev) +static int s3c24xx_serial_remove(struct device *_dev) { struct uart_port *port = s3c24xx_dev_to_port(_dev); @@ -1134,7 +1134,8 @@ int s3c24xx_serial_remove(struct device *_dev) #ifdef CONFIG_PM -int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, u32 level) +static int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, + u32 level) { struct uart_port *port = s3c24xx_dev_to_port(dev); @@ -1144,7 +1145,7 @@ int s3c24xx_serial_suspend(struct device *dev, pm_message_t state, u32 level) return 0; } -int s3c24xx_serial_resume(struct device *dev, u32 level) +static int s3c24xx_serial_resume(struct device *dev, u32 level) { struct uart_port *port = s3c24xx_dev_to_port(dev); struct s3c24xx_uart_port *ourport = to_ourport(port); @@ -1165,8 +1166,8 @@ int s3c24xx_serial_resume(struct device *dev, u32 level) #define s3c24xx_serial_resume NULL #endif -int s3c24xx_serial_init(struct device_driver *drv, - struct s3c24xx_uart_info *info) +static int s3c24xx_serial_init(struct device_driver *drv, + struct s3c24xx_uart_info *info) { dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); return driver_register(drv); -- cgit v0.10.2 From a7b1bbbc89194deba8cde02200f08b3840c9daa2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 19:58:07 +0100 Subject: [ARM] 2977/1: armksyms.c - make items in export table static Patch from Ben Dooks The items in the export table do not need to be exported elsehwere, so quash the sparse warning by making the symbol for the table entry static. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 835d450..7b17a87 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -45,8 +45,8 @@ extern void fp_enter(void); #define EXPORT_SYMBOL_ALIAS(sym,orig) \ EXPORT_CRC_ALIAS(sym) \ - const struct kernel_symbol __ksymtab_##sym \ - __attribute__((section("__ksymtab"))) = \ + static const struct kernel_symbol __ksymtab_##sym \ + __attribute_used__ __attribute__((section("__ksymtab"))) = \ { (unsigned long)&orig, #sym }; /* -- cgit v0.10.2 From 9f693d7b149a74bac301ee47136359294cffed25 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 19:58:07 +0100 Subject: [ARM] 2979/2: S3C2410 - add static to non-exported machine items Patch from Ben Dooks Do not export items that are not needed by symbol name elsewhere Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index 7c05f27..5ae80f4 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c @@ -125,7 +125,7 @@ static int external_map[] = { 2 }; static int chip0_map[] = { 0 }; static int chip1_map[] = { 1 }; -struct mtd_partition anubis_default_nand_part[] = { +static struct mtd_partition anubis_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_16K, diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index ed1f07d..8ca9559 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -230,7 +230,7 @@ static int chip0_map[] = { 1 }; static int chip1_map[] = { 2 }; static int chip2_map[] = { 3 }; -struct mtd_partition bast_default_nand_part[] = { +static struct mtd_partition bast_default_nand_part[] = { [0] = { .name = "Boot Agent", .size = SZ_16K, @@ -340,7 +340,7 @@ static struct resource bast_dm9k_resource[] = { * better IO routines can be written and tested */ -struct dm9000_plat_data bast_dm9k_platdata = { +static struct dm9000_plat_data bast_dm9k_platdata = { .flags = DM9000_PLATF_16BITONLY }; diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 663a7f9..46b2596 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -288,7 +288,7 @@ static struct resource vr1000_dm9k1_resource[] = { * better IO routines can be written and tested */ -struct dm9000_plat_data vr1000_dm9k_platdata = { +static struct dm9000_plat_data vr1000_dm9k_platdata = { .flags = DM9000_PLATF_16BITONLY, }; -- cgit v0.10.2 From ceca629e0b4858d6b8bff260dab2e947d31aca56 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Oct 2005 19:58:08 +0100 Subject: [ARM] 2971/1: i.MX uart handle rts irq Patch from Sascha Hauer handle rts interrupt Signed-off-by: Giancarlo Formicuccia Signed-off-by: Sascha Hauer diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 53e0323..bdb4e45 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -73,7 +73,7 @@ struct imx_port { struct uart_port port; struct timer_list timer; unsigned int old_status; - int txirq,rxirq; + int txirq,rxirq,rtsirq; }; /* @@ -181,6 +181,22 @@ static void imx_start_tx(struct uart_port *port) imx_transmit_buffer(sport); } +static irqreturn_t imx_rtsint(int irq, void *dev_id, struct pt_regs *regs) +{ + struct imx_port *sport = (struct imx_port *)dev_id; + unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + + USR1((u32)sport->port.membase) = USR1_RTSD; + uart_handle_cts_change(&sport->port, !!val); + wake_up_interruptible(&sport->port.info->delta_msr_wait); + + spin_unlock_irqrestore(&sport->port.lock, flags); + return IRQ_HANDLED; +} + static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) { struct imx_port *sport = (struct imx_port *)dev_id; @@ -386,15 +402,21 @@ static int imx_startup(struct uart_port *port) if (retval) goto error_out1; retval = request_irq(sport->txirq, imx_txint, 0, - "imx-uart", sport); + DRIVER_NAME, sport); if (retval) goto error_out2; + retval = request_irq(sport->rtsirq, imx_rtsint, 0, + DRIVER_NAME, sport); + if (retval) goto error_out3; + set_irq_type(sport->rtsirq, IRQT_BOTHEDGE); + /* * Finally, clear and enable interrupts */ + USR1((u32)sport->port.membase) = USR1_RTSD; UCR1((u32)sport->port.membase) |= - (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN); + (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN); /* @@ -406,6 +428,8 @@ static int imx_startup(struct uart_port *port) return 0; +error_out3: + free_irq(sport->txirq, sport); error_out2: free_irq(sport->rxirq, sport); error_out1: @@ -424,6 +448,7 @@ static void imx_shutdown(struct uart_port *port) /* * Free the interrupts */ + free_irq(sport->rtsirq, sport); free_irq(sport->txirq, sport); free_irq(sport->rxirq, sport); @@ -432,7 +457,7 @@ static void imx_shutdown(struct uart_port *port) */ UCR1((u32)sport->port.membase) &= - ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_UARTEN); + ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); } static void @@ -522,7 +547,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios, * disable interrupts and drain transmitter */ old_ucr1 = UCR1((u32)sport->port.membase); - UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN); + UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); while ( !(USR2((u32)sport->port.membase) & USR2_TXDC)) barrier(); @@ -643,6 +668,7 @@ static struct imx_port imx_ports[] = { { .txirq = UART1_MINT_TX, .rxirq = UART1_MINT_RX, + .rtsirq = UART1_MINT_RTS, .port = { .type = PORT_IMX, .iotype = SERIAL_IO_MEM, @@ -658,6 +684,7 @@ static struct imx_port imx_ports[] = { }, { .txirq = UART2_MINT_TX, .rxirq = UART2_MINT_RX, + .rtsirq = UART2_MINT_RTS, .port = { .type = PORT_IMX, .iotype = SERIAL_IO_MEM, @@ -737,7 +764,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) UCR1((u32)sport->port.membase) = (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) - & ~(UCR1_TXMPTYEN | UCR1_RRDYEN); + & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; /* -- cgit v0.10.2 From cd26f45bfca4d4fa5ddfe21613d2da46f1acb821 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Wed, 12 Oct 2005 19:58:09 +0100 Subject: [ARM] 2970/1: Use -mtune=arm1136j-s when building for CPU_V6 targets Patch from George G. Davis When building for CPU_V6 targets, we should use -mtune=arm1136j-s rather than -mtune=strongarm but fall back to the later in case someone is using an older toolchain (although they should really upgrade instead). Signed-off-by: George G. Davis Signed-off-by: Russell King diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 7779f2d..299bc04 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -53,7 +53,7 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale -tune-$(CONFIG_CPU_V6) :=-mtune=strongarm +tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) # Need -Uarm for gcc < 3.x CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) -- cgit v0.10.2 From 737d0bb7701cdebb661e4db0236071a7df977777 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Wed, 12 Oct 2005 19:58:10 +0100 Subject: [ARM] 2969/1: miscellaneous whitespace cleanup Patch from George G. Davis Fix leading, trailing and other miscellaneous whitespace issues in arch/arm/kernel/alignment.c. Signed-off-by: George G. Davis Signed-off-by: Russell King diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index f35e69e..705c989 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -111,7 +111,7 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, } static int proc_alignment_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { char mode; @@ -119,7 +119,7 @@ static int proc_alignment_write(struct file *file, const char __user *buffer, if (get_user(mode, buffer)) return -EFAULT; if (mode >= '0' && mode <= '5') - ai_usermode = mode - '0'; + ai_usermode = mode - '0'; } return count; } @@ -262,7 +262,7 @@ union offset_union { goto fault; \ } while (0) -#define put32_unaligned_check(val,addr) \ +#define put32_unaligned_check(val,addr) \ __put32_unaligned_check("strb", val, addr) #define put32t_unaligned_check(val,addr) \ @@ -306,19 +306,19 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r return TYPE_LDST; user: - if (LDST_L_BIT(instr)) { - unsigned long val; - get16t_unaligned_check(val, addr); + if (LDST_L_BIT(instr)) { + unsigned long val; + get16t_unaligned_check(val, addr); - /* signed half-word? */ - if (instr & 0x40) - val = (signed long)((signed short) val); + /* signed half-word? */ + if (instr & 0x40) + val = (signed long)((signed short) val); - regs->uregs[rd] = val; - } else - put16t_unaligned_check(regs->uregs[rd], addr); + regs->uregs[rd] = val; + } else + put16t_unaligned_check(regs->uregs[rd], addr); - return TYPE_LDST; + return TYPE_LDST; fault: return TYPE_FAULT; @@ -342,11 +342,11 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, unsigned long val; get32_unaligned_check(val, addr); regs->uregs[rd] = val; - get32_unaligned_check(val, addr+4); - regs->uregs[rd+1] = val; + get32_unaligned_check(val, addr + 4); + regs->uregs[rd + 1] = val; } else { put32_unaligned_check(regs->uregs[rd], addr); - put32_unaligned_check(regs->uregs[rd+1], addr+4); + put32_unaligned_check(regs->uregs[rd + 1], addr + 4); } return TYPE_LDST; @@ -356,11 +356,11 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, unsigned long val; get32t_unaligned_check(val, addr); regs->uregs[rd] = val; - get32t_unaligned_check(val, addr+4); - regs->uregs[rd+1] = val; + get32t_unaligned_check(val, addr + 4); + regs->uregs[rd + 1] = val; } else { put32t_unaligned_check(regs->uregs[rd], addr); - put32t_unaligned_check(regs->uregs[rd+1], addr+4); + put32t_unaligned_check(regs->uregs[rd + 1], addr + 4); } return TYPE_LDST; @@ -443,7 +443,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg if (LDST_P_EQ_U(instr)) /* U = P */ eaddr += 4; - /* + /* * For alignment faults on the ARM922T/ARM920T the MMU makes * the FSR (and hence addr) equal to the updated base address * of the multiple access rather than the restored value. @@ -570,7 +570,7 @@ thumb2arm(u16 tinstr) /* 6.5.1 Format 3: */ case 0x4800 >> 11: /* 7.1.28 LDR(3) */ /* NOTE: This case is not technically possible. We're - * loading 32-bit memory data via PC relative + * loading 32-bit memory data via PC relative * addressing mode. So we can and should eliminate * this case. But I'll leave it here for now. */ @@ -642,7 +642,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (fault) { type = TYPE_FAULT; - goto bad_or_fault; + goto bad_or_fault; } if (user_mode(regs)) -- cgit v0.10.2 From 6ec5e7f3656f0397b7e8b39a7dcc77937d187596 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 19:58:10 +0100 Subject: [ARM] 2978/1: nwfpe - clean up sparse errors Patch from Ben Dooks The NWFPE is producing a number of errors from sparse due to not defining a number of functions in the header files. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index 7690f73..7b3d74d 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -31,11 +31,6 @@ #include #include -/* forward declarations */ -unsigned int EmulateCPDO(const unsigned int); -unsigned int EmulateCPDT(const unsigned int); -unsigned int EmulateCPRT(const unsigned int); - /* Reset the FPA11 chip. Called to initialize and reset the emulator. */ static void resetFPA11(void) { diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index 93523ae..9677ae8 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -95,4 +95,24 @@ extern int8 SetRoundingMode(const unsigned int); extern int8 SetRoundingPrecision(const unsigned int); extern void nwfpe_init_fpa(union fp_state *fp); +extern unsigned int EmulateAll(unsigned int opcode); + +extern unsigned int EmulateCPDT(const unsigned int opcode); +extern unsigned int EmulateCPDO(const unsigned int opcode); +extern unsigned int EmulateCPRT(const unsigned int opcode); + +/* fpa11_cpdt.c */ +extern unsigned int PerformLDF(const unsigned int opcode); +extern unsigned int PerformSTF(const unsigned int opcode); +extern unsigned int PerformLFM(const unsigned int opcode); +extern unsigned int PerformSFM(const unsigned int opcode); + +/* single_cpdo.c */ + +extern unsigned int SingleCPDO(struct roundingData *roundData, + const unsigned int opcode, FPREG * rFd); +/* double_cpdo.c */ +extern unsigned int DoubleCPDO(struct roundingData *roundData, + const unsigned int opcode, FPREG * rFd); + #endif diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index adf8d30..7c67023 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -26,12 +26,11 @@ #include "fpa11.inl" #include "fpmodule.h" #include "fpmodule.inl" +#include "softfloat.h" #ifdef CONFIG_FPE_NWFPE_XP extern flag floatx80_is_nan(floatx80); #endif -extern flag float64_is_nan(float64); -extern flag float32_is_nan(float32); unsigned int PerformFLT(const unsigned int opcode); unsigned int PerformFIX(const unsigned int opcode); diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h index 1777e92..6528e08 100644 --- a/arch/arm/nwfpe/fpopcode.h +++ b/arch/arm/nwfpe/fpopcode.h @@ -476,4 +476,10 @@ static inline unsigned int getDestinationSize(const unsigned int opcode) return (nRc); } +extern unsigned int checkCondition(const unsigned int opcode, + const unsigned int ccodes); + +extern const float64 float64Constant[]; +extern const float32 float32Constant[]; + #endif diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 1c8799b..1415170 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -265,4 +265,7 @@ static inline flag float64_lt_nocheck(float64 a, float64 b) return (a != b) && (aSign ^ (a < b)); } +extern flag float32_is_nan( float32 a ); +extern flag float64_is_nan( float64 a ); + #endif -- cgit v0.10.2 From e6158b4a5647624ceb90074bfcc248ea3152c906 Mon Sep 17 00:00:00 2001 From: Lothar Wassmann Date: Wed, 12 Oct 2005 19:58:11 +0100 Subject: [ARM] 3002/1: Wrong parameter to uart_update_timeout() in drivers/serial/pxa.c Patch from Lothar Wassmann The function serial_pxa_set_termios() is calling uart_update_timeout() with the baud rate divisor as third parameter, while uart_update_timeout() expects the baud rate in this place. This results in a bogus port->timeout which is proportional to the baud rate. Signed-off-by: Lothar Wassmann Signed-off-by: Russell King diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 672b359..90c2a86 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -499,7 +499,7 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios, /* * Update the per-port timeout. */ - uart_update_timeout(port, termios->c_cflag, quot); + uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) -- cgit v0.10.2 From a451e28c7642830d8b066e5a13de46934151ce3a Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 12 Oct 2005 19:58:12 +0100 Subject: [ARM] 3003/1: SSP channel map register updates for pxa2xx Patch from Liam Girdwood This patch updates the pxa2xx channel map registers definitions in pxa-regs.h Changes:- o Added description for SSP2 registers o Added definitions for SSP3 registers Signed-off-by:Liam Girdwood Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 939d9e5..13fa2de 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -126,8 +126,8 @@ #define DRCMR12 __REG(0x40000130) /* Request to Channel Map Register for AC97 audio transmit Request */ #define DRCMR13 __REG(0x40000134) /* Request to Channel Map Register for SSP receive Request */ #define DRCMR14 __REG(0x40000138) /* Request to Channel Map Register for SSP transmit Request */ -#define DRCMR15 __REG(0x4000013c) /* Reserved */ -#define DRCMR16 __REG(0x40000140) /* Reserved */ +#define DRCMR15 __REG(0x4000013c) /* Request to Channel Map Register for SSP2 receive Request */ +#define DRCMR16 __REG(0x40000140) /* Request to Channel Map Register for SSP2 transmit Request */ #define DRCMR17 __REG(0x40000144) /* Request to Channel Map Register for ICP receive Request */ #define DRCMR18 __REG(0x40000148) /* Request to Channel Map Register for ICP transmit Request */ #define DRCMR19 __REG(0x4000014c) /* Request to Channel Map Register for STUART receive Request */ @@ -151,7 +151,8 @@ #define DRCMR37 __REG(0x40000194) /* Request to Channel Map Register for USB endpoint 13 Request */ #define DRCMR38 __REG(0x40000198) /* Request to Channel Map Register for USB endpoint 14 Request */ #define DRCMR39 __REG(0x4000019C) /* Reserved */ - +#define DRCMR66 __REG(0x40001108) /* Request to Channel Map Register for SSP3 receive Request */ +#define DRCMR67 __REG(0x4000110C) /* Request to Channel Map Register for SSP3 transmit Request */ #define DRCMR68 __REG(0x40001110) /* Request to Channel Map Register for Camera FIFO 0 Request */ #define DRCMR69 __REG(0x40001114) /* Request to Channel Map Register for Camera FIFO 1 Request */ #define DRCMR70 __REG(0x40001118) /* Request to Channel Map Register for Camera FIFO 2 Request */ -- cgit v0.10.2 From c9c10830740df1b5e7848d6fbb68c93a73e8f7cd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 12 Oct 2005 12:22:46 -0700 Subject: [SPARC64]: Fix boot failures on SunBlade-150 The sequence to move over to the Linux trap tables from the firmware ones needs to be more air tight. It turns out that to be %100 safe we do need to be able to translate OBP mappings in our TLB miss handlers early. In order not to eat up a lot of kernel image memory with static page tables, just use the translations array in the OBP TLB miss handlers. That solves the bulk of the problem. Furthermore, to make sure the OBP TLB miss path will work even before the fixed MMU globals are loaded, explicitly load %g1 to TLB_SFSR at the beginning of the i-TLB and d-TLB miss handlers. To ease the OBP TLB miss walking of the prom_trans[] array, we sort it then delete all of the non-OBP entries in there (for example, there are entries for the kernel image itself which we're not interested in at all). We also save about 32K of kernel image size with this change. Not a bad side effect :-) There are still some reasons why trampoline.S can't use the setup_trap_table() yet. The most noteworthy are: 1) OBP boots secondary processors with non-bias'd stack for some reason. This is easily fixed by using a small bootup stack in the kernel image explicitly for this purpose. 2) Doing a firmware call via the normal C call prom_set_trap_table() goes through the whole OBP enter/exit sequence that saves and restores OBP and Linux kernel state in the MMUs. This path unfortunately does a "flush %g6" while loading up the OBP locked TLB entries for the firmware call. If we setup the %g6 in the trampoline.S code properly, that is in the PAGE_OFFSET linear mapping, but we're not on the kernel trap table yet so those addresses won't translate properly. One idea is to do a by-hand firmware call like we do in the early bootup code and elsewhere here in trampoline.S But this fails as well, as aparently the secondary processors are not booted with OBP's special locked TLB entries loaded. These are necessary for the firwmare to processes TLB misses correctly up until the point where we take over the trap table. This does need to be resolved at some point. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S index 702d349..6528786 100644 --- a/arch/sparc64/kernel/dtlb_base.S +++ b/arch/sparc64/kernel/dtlb_base.S @@ -53,19 +53,18 @@ * be guaranteed to be 0 ... mmu_context.h does guarantee this * by only using 10 bits in the hwcontext value. */ -#define CREATE_VPTE_OFFSET1(r1, r2) +#define CREATE_VPTE_OFFSET1(r1, r2) nop #define CREATE_VPTE_OFFSET2(r1, r2) \ srax r1, 10, r2 -#define CREATE_VPTE_NOP nop #else #define CREATE_VPTE_OFFSET1(r1, r2) \ srax r1, PAGE_SHIFT, r2 #define CREATE_VPTE_OFFSET2(r1, r2) \ sllx r2, 3, r2 -#define CREATE_VPTE_NOP #endif /* DTLB ** ICACHE line 1: Quick user TLB misses */ + mov TLB_SFSR, %g1 ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? from_tl1_trap: @@ -74,18 +73,16 @@ from_tl1_trap: be,pn %xcc, kvmap ! Yep, special processing CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset cmp %g5, 4 ! Last trap level? - be,pn %xcc, longpath ! Yep, cannot risk VPTE miss - nop ! delay slot /* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */ + be,pn %xcc, longpath ! Yep, cannot risk VPTE miss + nop ! delay slot ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE 1: brgez,pn %g5, longpath ! Invalid, branch out nop ! Delay-slot 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB retry ! Trap return nop - nop - nop /* DTLB ** ICACHE line 3: winfixups+real_faults */ longpath: @@ -106,8 +103,7 @@ longpath: nop nop nop - CREATE_VPTE_NOP + nop #undef CREATE_VPTE_OFFSET1 #undef CREATE_VPTE_OFFSET2 -#undef CREATE_VPTE_NOP diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc64/kernel/dtlb_prot.S index d848bb7..e0a9201 100644 --- a/arch/sparc64/kernel/dtlb_prot.S +++ b/arch/sparc64/kernel/dtlb_prot.S @@ -14,14 +14,14 @@ */ /* PROT ** ICACHE line 1: User DTLB protection trap */ - stxa %g0, [%g1] ASI_DMMU ! Clear SFSR FaultValid bit - membar #Sync ! Synchronize ASI stores - rdpr %pstate, %g5 ! Move into alternate globals + mov TLB_SFSR, %g1 + stxa %g0, [%g1] ASI_DMMU ! Clear FaultValid bit + membar #Sync ! Synchronize stores + rdpr %pstate, %g5 ! Move into alt-globals wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g1 ! Need to do a winfixup? + rdpr %tl, %g1 ! Need a winfixup? cmp %g1, 1 ! Trap level >1? - mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr - nop + mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr /* PROT ** ICACHE line 2: More real fault processing */ bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 4c942f7..b49dcd4 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -28,19 +28,14 @@ #include /* This section from from _start to sparc64_boot_end should fit into - * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space - * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to - * 0x0000.0000.0040.6000 and empty_bad_page, which is from - * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000. + * 0x0000000000404000 to 0x0000000000408000. */ - .text .globl start, _start, stext, _stext _start: start: _stext: stext: -bootup_user_stack: ! 0x0000000000404000 b sparc64_boot flushw /* Flush register file. */ @@ -392,31 +387,30 @@ tlb_fixup_done: * former does use this code, the latter does not yet due * to some complexities. That should be fixed up at some * point. + * + * There used to be enormous complexity wrt. transferring + * over from the firwmare's trap table to the Linux kernel's. + * For example, there was a chicken & egg problem wrt. building + * the OBP page tables, yet needing to be on the Linux kernel + * trap table (to translate PAGE_OFFSET addresses) in order to + * do that. + * + * We now handle OBP tlb misses differently, via linear lookups + * into the prom_trans[] array. So that specific problem no + * longer exists. Yet, unfortunately there are still some issues + * preventing trampoline.S from using this code... ho hum. */ .globl setup_trap_table setup_trap_table: save %sp, -192, %sp - /* Force interrupts to be disabled. Transferring over to - * the Linux trap table is a very delicate operation. - * Until we are actually on the Linux trap table, we cannot - * get the PAGE_OFFSET linear mappings translated. We need - * that mapping to be setup in order to initialize the firmware - * page tables. - * - * So there is this window of time, from the return from - * prom_set_trap_table() until inherit_prom_mappings_post() - * (in arch/sparc64/mm/init.c) completes, during which no - * firmware address space accesses can be made. - */ + /* Force interrupts to be disabled. */ rdpr %pstate, %o1 andn %o1, PSTATE_IE, %o1 wrpr %o1, 0x0, %pstate wrpr %g0, 15, %pil - /* Ok, now make the final valid firmware call to jump over - * to the Linux trap table. - */ + /* Make the firmware call to jump over to the Linux trap table. */ call prom_set_trap_table sethi %hi(sparc64_ttable_tl0), %o0 @@ -540,15 +534,21 @@ setup_tba: /* i0 = is_starfire */ ret restore +sparc64_boot_end: + +#include "systbls.S" +#include "ktlb.S" +#include "etrap.S" +#include "rtrap.S" +#include "winfixup.S" +#include "entry.S" /* - * The following skips make sure the trap table in ttable.S is aligned + * The following skip makes sure the trap table in ttable.S is aligned * on a 32K boundary as required by the v9 specs for TBA register. */ -sparc64_boot_end: - .skip 0x2000 + _start - sparc64_boot_end -bootup_user_stack_end: - .skip 0x2000 +1: + .skip 0x4000 + _start - 1b #ifdef CONFIG_SBUS /* This is just a hack to fool make depend config.h discovering @@ -560,15 +560,6 @@ bootup_user_stack_end: ! 0x0000000000408000 #include "ttable.S" -#include "systbls.S" -#include "ktlb.S" -#include "etrap.S" -#include "rtrap.S" -#include "winfixup.S" -#include "entry.S" - - /* This is just anal retentiveness on my part... */ - .align 16384 .data .align 8 diff --git a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S index b5e32df..4951ff8 100644 --- a/arch/sparc64/kernel/itlb_base.S +++ b/arch/sparc64/kernel/itlb_base.S @@ -15,14 +15,12 @@ */ #define CREATE_VPTE_OFFSET1(r1, r2) \ srax r1, 10, r2 -#define CREATE_VPTE_OFFSET2(r1, r2) -#define CREATE_VPTE_NOP nop +#define CREATE_VPTE_OFFSET2(r1, r2) nop #else /* PAGE_SHIFT */ #define CREATE_VPTE_OFFSET1(r1, r2) \ srax r1, PAGE_SHIFT, r2 #define CREATE_VPTE_OFFSET2(r1, r2) \ sllx r2, 3, r2 -#define CREATE_VPTE_NOP #endif /* PAGE_SHIFT */ @@ -36,6 +34,7 @@ */ /* ITLB ** ICACHE line 1: Quick user TLB misses */ + mov TLB_SFSR, %g1 ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset @@ -43,41 +42,38 @@ 1: brgez,pn %g5, 3f ! Not valid, branch out sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot andcc %g5, %g4, %g0 ! Executable? + +/* ITLB ** ICACHE line 2: Real faults */ be,pn %xcc, 3f ! Nope, branch. nop ! Delay-slot 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB retry ! Trap return -3: rdpr %pstate, %g4 ! Move into alternate globals - -/* ITLB ** ICACHE line 2: Real faults */ +3: rdpr %pstate, %g4 ! Move into alt-globals wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate rdpr %tpc, %g5 ! And load faulting VA mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB -sparc64_realfault_common: ! Called by TL0 dtlb_miss too + +/* ITLB ** ICACHE line 3: Finish faults */ +sparc64_realfault_common: ! Called by dtlb_miss stb %g4, [%g6 + TI_FAULT_CODE] stx %g5, [%g6 + TI_FAULT_ADDR] ba,pt %xcc, etrap ! Save state 1: rd %pc, %g7 ! ... - nop - -/* ITLB ** ICACHE line 3: Finish faults + window fixups */ call do_sparc64_fault ! Call fault handler add %sp, PTREGS_OFF, %o0! Compute pt_regs arg ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state nop + +/* ITLB ** ICACHE line 4: Window fixups */ winfix_trampoline: rdpr %tpc, %g3 ! Prepare winfixup TNPC - or %g3, 0x7c, %g3 ! Compute offset to branch + or %g3, 0x7c, %g3 ! Compute branch offset wrpr %g3, %tnpc ! Write it into TNPC done ! Do it to it - -/* ITLB ** ICACHE line 4: Unused... */ nop nop nop nop - CREATE_VPTE_NOP #undef CREATE_VPTE_OFFSET1 #undef CREATE_VPTE_OFFSET2 -#undef CREATE_VPTE_NOP diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S index 7796b37..d9244d3 100644 --- a/arch/sparc64/kernel/ktlb.S +++ b/arch/sparc64/kernel/ktlb.S @@ -58,9 +58,6 @@ vpte_noent: done vpte_insn_obp: - sethi %hi(prom_pmd_phys), %g5 - ldx [%g5 + %lo(prom_pmd_phys)], %g5 - /* Behave as if we are at TL0. */ wrpr %g0, 1, %tl rdpr %tpc, %g4 /* Find original faulting iaddr */ @@ -71,58 +68,57 @@ vpte_insn_obp: mov TLB_SFSR, %g1 stxa %g4, [%g1 + %g1] ASI_IMMU - /* Get PMD offset. */ - srlx %g4, 23, %g6 - and %g6, 0x7ff, %g6 - sllx %g6, 2, %g6 - - /* Load PMD, is it valid? */ - lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - sllx %g5, 11, %g5 - - /* Get PTE offset. */ - srlx %g4, 13, %g6 - and %g6, 0x3ff, %g6 - sllx %g6, 3, %g6 - - /* Load PTE. */ - ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brgez,pn %g5, longpath - nop - - /* TLB load and return from trap. */ + sethi %hi(prom_trans), %g5 + or %g5, %lo(prom_trans), %g5 + +1: ldx [%g5 + 0x00], %g6 ! base + brz,a,pn %g6, longpath ! no more entries, fail + mov TLB_SFSR, %g1 ! and restore %g1 + ldx [%g5 + 0x08], %g1 ! len + add %g6, %g1, %g1 ! end + cmp %g6, %g4 + bgu,pt %xcc, 2f + cmp %g4, %g1 + bgeu,pt %xcc, 2f + ldx [%g5 + 0x10], %g1 ! PTE + + /* TLB load, restore %g1, and return from trap. */ + sub %g4, %g6, %g6 + add %g1, %g6, %g5 + mov TLB_SFSR, %g1 stxa %g5, [%g0] ASI_ITLB_DATA_IN retry -kvmap_do_obp: - sethi %hi(prom_pmd_phys), %g5 - ldx [%g5 + %lo(prom_pmd_phys)], %g5 - - /* Get PMD offset. */ - srlx %g4, 23, %g6 - and %g6, 0x7ff, %g6 - sllx %g6, 2, %g6 - - /* Load PMD, is it valid? */ - lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brz,pn %g5, longpath - sllx %g5, 11, %g5 - - /* Get PTE offset. */ - srlx %g4, 13, %g6 - and %g6, 0x3ff, %g6 - sllx %g6, 3, %g6 - - /* Load PTE. */ - ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5 - brgez,pn %g5, longpath - nop +2: ba,pt %xcc, 1b + add %g5, (3 * 8), %g5 ! next entry - /* TLB load and return from trap. */ +kvmap_do_obp: + sethi %hi(prom_trans), %g5 + or %g5, %lo(prom_trans), %g5 + srlx %g4, 13, %g4 + sllx %g4, 13, %g4 + +1: ldx [%g5 + 0x00], %g6 ! base + brz,a,pn %g6, longpath ! no more entries, fail + mov TLB_SFSR, %g1 ! and restore %g1 + ldx [%g5 + 0x08], %g1 ! len + add %g6, %g1, %g1 ! end + cmp %g6, %g4 + bgu,pt %xcc, 2f + cmp %g4, %g1 + bgeu,pt %xcc, 2f + ldx [%g5 + 0x10], %g1 ! PTE + + /* TLB load, restore %g1, and return from trap. */ + sub %g4, %g6, %g6 + add %g1, %g6, %g5 + mov TLB_SFSR, %g1 stxa %g5, [%g0] ASI_DTLB_DATA_IN retry +2: ba,pt %xcc, 1b + add %g5, (3 * 8), %g5 ! next entry + /* * On a first level data miss, check whether this is to the OBP range (note * that such accesses can be made by prom, as well as by kernel using diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 0d2e967..1e44ee2 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -105,7 +105,7 @@ static void __init read_obp_memory(const char *property, regs[i].phys_addr = base; regs[i].reg_size = size; } - sort(regs, ents, sizeof(struct linux_prom64_registers), + sort(regs, ents, sizeof(struct linux_prom64_registers), cmp_p64, NULL); } @@ -367,8 +367,11 @@ struct linux_prom_translation { unsigned long size; unsigned long data; }; -static struct linux_prom_translation prom_trans[512] __initdata; -static unsigned int prom_trans_ents __initdata; + +/* Exported for kernel TLB miss handling in ktlb.S */ +struct linux_prom_translation prom_trans[512] __read_mostly; +unsigned int prom_trans_ents __read_mostly; +unsigned int swapper_pgd_zero __read_mostly; extern unsigned long prom_boot_page; extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle); @@ -378,122 +381,57 @@ extern void register_prom_callbacks(void); /* Exported for SMP bootup purposes. */ unsigned long kern_locked_tte_data; -/* Exported for kernel TLB miss handling in ktlb.S */ -unsigned long prom_pmd_phys __read_mostly; -unsigned int swapper_pgd_zero __read_mostly; - -static pmd_t *prompmd __read_mostly; - -#define BASE_PAGE_SIZE 8192 - /* * Translate PROM's mapping we capture at boot time into physical address. * The second parameter is only set from prom_callback() invocations. */ unsigned long prom_virt_to_phys(unsigned long promva, int *error) { - pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff); - pte_t *ptep; - unsigned long base; - - if (pmd_none(*pmdp)) { - if (error) - *error = 1; - return 0; - } - ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff); - if (!pte_present(*ptep)) { - if (error) - *error = 1; - return 0; - } - if (error) { - *error = 0; - return pte_val(*ptep); - } - base = pte_val(*ptep) & _PAGE_PADDR; - - return base + (promva & (BASE_PAGE_SIZE - 1)); -} + int i; -/* The obp translations are saved based on 8k pagesize, since obp can - * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS -> - * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte - * scheme (also, see rant in inherit_locked_prom_mappings()). - */ -static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data) -{ - unsigned long vaddr; + for (i = 0; i < prom_trans_ents; i++) { + struct linux_prom_translation *p = &prom_trans[i]; - for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) { - unsigned long val; - pmd_t *pmd; - pte_t *pte; + if (promva >= p->virt && + promva < (p->virt + p->size)) { + unsigned long base = p->data & _PAGE_PADDR; - pmd = prompmd + ((vaddr >> 23) & 0x7ff); - if (pmd_none(*pmd)) { - pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE, - PAGE_SIZE); - if (!pte) - prom_halt(); - memset(pte, 0, BASE_PAGE_SIZE); - pmd_set(pmd, pte); + if (error) + *error = 0; + return base + (promva & (8192 - 1)); } - pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff); - - val = data; - - /* Clear diag TTE bits. */ - if (tlb_type == spitfire) - val &= ~0x0003fe0000000000UL; - - set_pte_at(&init_mm, vaddr, pte, - __pte(val | _PAGE_MODIFIED)); - - data += BASE_PAGE_SIZE; } + if (error) + *error = 1; + return 0UL; } +/* The obp translations are saved based on 8k pagesize, since obp can + * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS -> + * HI_OBP_ADDRESS range are handled in ktlb.S and do not use the vpte + * scheme (also, see rant in inherit_locked_prom_mappings()). + */ static inline int in_obp_range(unsigned long vaddr) { return (vaddr >= LOW_OBP_ADDRESS && vaddr < HI_OBP_ADDRESS); } -#define OBP_PMD_SIZE 2048 -static void __init build_obp_pgtable(void) +static int cmp_ptrans(const void *a, const void *b) { - unsigned long i; - - prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE); - if (!prompmd) - prom_halt(); - - memset(prompmd, 0, OBP_PMD_SIZE); - - prom_pmd_phys = __pa(prompmd); - - for (i = 0; i < prom_trans_ents; i++) { - unsigned long start, end; - - if (!in_obp_range(prom_trans[i].virt)) - continue; + const struct linux_prom_translation *x = a, *y = b; - start = prom_trans[i].virt; - end = start + prom_trans[i].size; - if (end > HI_OBP_ADDRESS) - end = HI_OBP_ADDRESS; - - build_obp_range(start, end, prom_trans[i].data); - } + if (x->virt > y->virt) + return 1; + if (x->virt < y->virt) + return -1; + return 0; } -/* Read OBP translations property into 'prom_trans[]'. - * Return the number of entries. - */ +/* Read OBP translations property into 'prom_trans[]'. */ static void __init read_obp_translations(void) { - int n, node; + int n, node, ents, first, last, i; node = prom_finddevice("/virtual-memory"); n = prom_getproplen(node, "translations"); @@ -515,7 +453,41 @@ static void __init read_obp_translations(void) n = n / sizeof(struct linux_prom_translation); - prom_trans_ents = n; + ents = n; + + sort(prom_trans, ents, sizeof(struct linux_prom_translation), + cmp_ptrans, NULL); + + /* Now kick out all the non-OBP entries. */ + for (i = 0; i < ents; i++) { + if (in_obp_range(prom_trans[i].virt)) + break; + } + first = i; + for (; i < ents; i++) { + if (!in_obp_range(prom_trans[i].virt)) + break; + } + last = i; + + for (i = 0; i < (last - first); i++) { + struct linux_prom_translation *src = &prom_trans[i + first]; + struct linux_prom_translation *dest = &prom_trans[i]; + + *dest = *src; + } + for (; i < ents; i++) { + struct linux_prom_translation *dest = &prom_trans[i]; + dest->virt = dest->size = dest->data = 0x0UL; + } + + prom_trans_ents = last - first; + + if (tlb_type == spitfire) { + /* Clear diag TTE bits. */ + for (i = 0; i < prom_trans_ents; i++) + prom_trans[i].data &= ~0x0003fe0000000000UL; + } } static void __init remap_kernel(void) @@ -553,21 +525,18 @@ static void __init remap_kernel(void) } -static void __init inherit_prom_mappings_pre(void) +static void __init inherit_prom_mappings(void) { read_obp_translations(); /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); remap_kernel(); - prom_printf("done.\n"); -} -static void __init inherit_prom_mappings_post(void) -{ - build_obp_pgtable(); + prom_printf("Registering callbacks... "); register_prom_callbacks(); + prom_printf("done.\n"); } /* The OBP specifications for sun4u mark 0xfffffffc00000000 and @@ -1519,7 +1488,7 @@ void __init paging_init(void) swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); - inherit_prom_mappings_pre(); + inherit_prom_mappings(); /* Ok, we can use our TLB miss and window trap handlers safely. * We need to do a quick peek here to see if we are on StarFire @@ -1530,23 +1499,15 @@ void __init paging_init(void) extern void setup_tba(int); setup_tba(this_is_starfire); } - __flush_tlb_all(); - /* Everything from this point forward, until we are done with - * inherit_prom_mappings_post(), must complete successfully - * without calling into the firmware. The firwmare page tables - * have not been built, but we are running on the Linux kernel's - * trap table. - */ + inherit_locked_prom_mappings(1); + + __flush_tlb_all(); /* Setup bootmem... */ pages_avail = 0; last_valid_pfn = end_pfn = bootmem_init(&pages_avail); - inherit_prom_mappings_post(); - - inherit_locked_prom_mappings(1); - #ifdef CONFIG_DEBUG_PAGEALLOC kernel_physical_mapping_init(); #endif -- cgit v0.10.2 From ab4060e858e36129f9319ef0fa055347ad60e1d5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 12 Oct 2005 15:10:01 -0700 Subject: [BRIDGE]: fix race on bridge del if This fixes the RCU race on bridge delete interface. Basically, the network device has to be detached from the bridge in the first step (pre-RCU), rather than later. At that point, no more bridge traffic will come in, and the other code will not think that network device is part of a bridge. This should also fix the XEN test problems. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 91bb895..defcf6a 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -79,7 +79,6 @@ static void destroy_nbp(struct net_bridge_port *p) { struct net_device *dev = p->dev; - dev->br_port = NULL; p->br = NULL; p->dev = NULL; dev_put(dev); @@ -100,6 +99,7 @@ static void del_nbp(struct net_bridge_port *p) struct net_bridge *br = p->br; struct net_device *dev = p->dev; + dev->br_port = NULL; dev_set_promiscuity(dev, -1); spin_lock_bh(&br->lock); -- cgit v0.10.2 From afb997c6163b33292d31a09d6aa5cbb03ffa5bf1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 12 Oct 2005 15:12:21 -0700 Subject: [NETPOLL]: wrong return for null netpoll_poll_lock() When netpoll is not being used, the macro that defines the removed routing netpoll_poll_lock defines the return as zero, but the real routine returns a `void *` Signed-off-by: Ben Dooks Signed-off-by: David S. Miller diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 5ade54a..ca5a873 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -86,7 +86,7 @@ static inline void netpoll_poll_unlock(void *have) #else #define netpoll_rx(a) 0 -#define netpoll_poll_lock(a) 0 +#define netpoll_poll_lock(a) NULL #define netpoll_poll_unlock(a) #endif -- cgit v0.10.2 From 9ff5c59ce278c37bca22fbf98076d199bcaf9845 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 12 Oct 2005 15:59:39 -0700 Subject: [TCP]: Add code to help track down "BUG at net/ipv4/tcp_output.c:438!" This is the second report of this bug. Unfortunately the first reporter hasn't been able to reproduce it since to provide more debugging info. So let's apply this patch for 2.6.14 to 1) Make this non-fatal. 2) Provide the info we need to track it down. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8225e42..f37a50e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -435,7 +435,14 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss int nsize, old_factor; u16 flags; - BUG_ON(len >= skb->len); + if (unlikely(len >= skb->len)) { + printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, " + "end_seq=%u, skb->len=%u.\n", len, mss_now, + TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, + skb->len); + WARN_ON(1); + return 0; + } nsize = skb_headlen(skb) - len; if (nsize < 0) -- cgit v0.10.2 From 9153bd75f25ff3170f07fb9ac1fb0e718afc6fce Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 13 Oct 2005 16:46:35 +0100 Subject: [ARM] 3005/1: S3C2440 - add definition for s3c2440_set_dsc() call in hardware.h Patch from Ben Dooks include/asm-arm/arch-s3c2410/hardware.h was missing the definition for s3c2440_set_dsc() Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h index 48a3991..1c9de29 100644 --- a/include/asm-arm/arch-s3c2410/hardware.h +++ b/include/asm-arm/arch-s3c2410/hardware.h @@ -92,6 +92,13 @@ extern unsigned int s3c2410_gpio_getpin(unsigned int pin); extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg); +#ifdef CONFIG_CPU_S3C2440 + +extern int s3c2440_set_dsc(unsigned int pin, unsigned int value); + +#endif /* CONFIG_CPU_S3C2440 */ + + #endif /* __ASSEMBLY__ */ #include -- cgit v0.10.2 From 3a8f675c40ba2d04e4fff6710db3da763436269f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 13 Oct 2005 16:46:35 +0100 Subject: [ARM] 3006/1: S3C2410 - arch/arm/mach-s3c2410 sparse fixes Patch from Ben Dooks Remove an unused variable from s3c2410.c and ensure that items not needed to be exported from s3c2440.c are declared static. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 0b88993..a8bf5ec 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -125,9 +125,6 @@ static struct platform_device *uart_devices[] __initdata = { &s3c_uart2 }; -/* store our uart devices for the serial driver console */ -struct platform_device *s3c2410_uart_devices[3]; - static int s3c2410_uart_count = 0; /* uart registration process */ diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c index d4c8281..833fa36 100644 --- a/arch/arm/mach-s3c2410/s3c2440.c +++ b/arch/arm/mach-s3c2410/s3c2440.c @@ -151,7 +151,7 @@ void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no) #ifdef CONFIG_PM -struct sleep_save s3c2440_sleep[] = { +static struct sleep_save s3c2440_sleep[] = { SAVE_ITEM(S3C2440_DSC0), SAVE_ITEM(S3C2440_DSC1), SAVE_ITEM(S3C2440_GPJDAT), @@ -260,7 +260,7 @@ void __init s3c2440_init_clocks(int xtal) * as a driver which may support both 2410 and 2440 may try and use it. */ -int __init s3c2440_core_init(void) +static int __init s3c2440_core_init(void) { return sysdev_class_register(&s3c2440_sysclass); } -- cgit v0.10.2 From 50688ea9ed6fe154058c065bc7dc60980533a2c8 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 13 Oct 2005 22:04:36 +0100 Subject: [ARM] 3007/1: BAST - add CONFIG_ISA to build Patch from Ben Dooks The Simtec EB2410ITX (BAST) has a PC/104 slot, and therefore we should enable CONFIG_ISA to allow the drivers for ISA peripherals to be selected Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 06807c6..c796bcd 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -12,6 +12,7 @@ config MACH_ANUBIS config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select CPU_S3C2410 + select ISA help Say Y here if you are using the Simtec Electronics EB2410ITX development board (also known as BAST) -- cgit v0.10.2 From 13b1f64c16e2eb96a021b49cf3986528046ba3dc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 13 Oct 2005 22:04:37 +0100 Subject: [ARM] 3008/1: the exception table is not read-only Patch from Nicolas Pitre ... and therefore should not live in the .text section. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 08e58ec..0d5db52 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -89,13 +89,6 @@ SECTIONS *(.got) /* Global offset table */ } - . = ALIGN(16); - __ex_table : { /* Exception table */ - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - RODATA _etext = .; /* End of text and rodata section */ @@ -138,6 +131,14 @@ SECTIONS *(.data.cacheline_aligned) /* + * The exception fixup table (might need resorting at runtime) + */ + . = ALIGN(32); + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + /* * and the usual data section */ *(.data) -- cgit v0.10.2 From c8923c6b852d3a97c1faad0566e38fca330375a7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 13 Oct 2005 14:41:23 -0700 Subject: [NETFILTER]: Fix OOPSes on machines with discontiguous cpu numbering. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original patch by Harald Welte, with feedback from Herbert Xu and testing by Sébastien Bernard. EBTABLES, ARP tables, and IP/IP6 tables all assume that cpus are numbered linearly. That is not necessarily true. This patch fixes that up by calculating the largest possible cpu number, and allocating enough per-cpu structure space given that. Signed-off-by: David S. Miller diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 2c5cae0..957f551 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -15,6 +15,7 @@ #include #include #include +#include #define IPI_SCHEDULE 1 #define IPI_CALL 2 @@ -28,6 +29,7 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; /* CPU masks */ cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; +EXPORT_SYMBOL(phys_cpu_present_map); /* Variables used during SMP boot */ volatile int cpu_now_booting = 0; diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 56a39d6..5ecefc0 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,8 @@ struct sh_cpuinfo cpu_data[NR_CPUS]; extern void per_cpu_trap_init(void); cpumask_t cpu_possible_map; +EXPORT_SYMBOL(cpu_possible_map); + cpumask_t cpu_online_map; static atomic_t cpus_booted = ATOMIC_INIT(0); diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index b15826f..fe97783 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -392,4 +392,16 @@ extern cpumask_t cpu_present_map; #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) +/* Find the highest possible smp_processor_id() */ +static inline unsigned int highest_possible_processor_id(void) +{ + unsigned int cpu, highest = 0; + + for_each_cpu_mask(cpu, cpu_possible_map) + highest = cpu; + + return highest; +} + + #endif /* __LINUX_CPUMASK_H */ diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index c454014..f8ffbf6 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -26,6 +26,7 @@ #include #include #include +#include #include /* needed for logical [in,out]-dev filtering */ #include "../br_private.h" @@ -823,10 +824,11 @@ static int translate_table(struct ebt_replace *repl, /* this will get free'd in do_replace()/ebt_register_table() if an error occurs */ newinfo->chainstack = (struct ebt_chainstack **) - vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack)); + vmalloc((highest_possible_processor_id()+1) + * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack) return -ENOMEM; - for (i = 0; i < num_possible_cpus(); i++) { + for_each_cpu(i) { newinfo->chainstack[i] = vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); if (!newinfo->chainstack[i]) { @@ -895,9 +897,12 @@ static void get_counters(struct ebt_counter *oldcounters, /* counters of cpu 0 */ memcpy(counters, oldcounters, - sizeof(struct ebt_counter) * nentries); + sizeof(struct ebt_counter) * nentries); + /* add other counters to those of cpu 0 */ - for (cpu = 1; cpu < num_possible_cpus(); cpu++) { + for_each_cpu(cpu) { + if (cpu == 0) + continue; counter_base = COUNTER_BASE(oldcounters, nentries, cpu); for (i = 0; i < nentries; i++) { counters[i].pcnt += counter_base[i].pcnt; @@ -929,7 +934,8 @@ static int do_replace(void __user *user, unsigned int len) BUGPRINT("Entries_size never zero\n"); return -EINVAL; } - countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus(); + countersize = COUNTER_OFFSET(tmp.nentries) * + (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); if (!newinfo) @@ -1022,7 +1028,7 @@ static int do_replace(void __user *user, unsigned int len) vfree(table->entries); if (table->chainstack) { - for (i = 0; i < num_possible_cpus(); i++) + for_each_cpu(i) vfree(table->chainstack[i]); vfree(table->chainstack); } @@ -1040,7 +1046,7 @@ free_counterstmp: vfree(counterstmp); /* can be initialized in translate_table() */ if (newinfo->chainstack) { - for (i = 0; i < num_possible_cpus(); i++) + for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } @@ -1132,7 +1138,8 @@ int ebt_register_table(struct ebt_table *table) return -EINVAL; } - countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus(); + countersize = COUNTER_OFFSET(table->table->nentries) * + (highest_possible_processor_id()+1); newinfo = (struct ebt_table_info *) vmalloc(sizeof(struct ebt_table_info) + countersize); ret = -ENOMEM; @@ -1186,7 +1193,7 @@ free_unlock: up(&ebt_mutex); free_chainstack: if (newinfo->chainstack) { - for (i = 0; i < num_possible_cpus(); i++) + for_each_cpu(i) vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } @@ -1209,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table) up(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { - for (i = 0; i < num_possible_cpus(); i++) + for_each_cpu(i) vfree(table->private->chainstack[i]); vfree(table->private->chainstack); } diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index fa16342..a796928 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -716,8 +716,10 @@ static int translate_table(const char *name, } /* And one copy for every other CPU */ - for (i = 1; i < num_possible_cpus(); i++) { - memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, + for_each_cpu(i) { + if (i == 0) + continue; + memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i, newinfo->entries, SMP_ALIGN(newinfo->size)); } @@ -767,7 +769,7 @@ static void get_counters(const struct arpt_table_info *t, unsigned int cpu; unsigned int i; - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { + for_each_cpu(cpu) { i = 0; ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), t->size, @@ -885,7 +887,8 @@ static int do_replace(void __user *user, unsigned int len) return -ENOMEM; newinfo = vmalloc(sizeof(struct arpt_table_info) - + SMP_ALIGN(tmp.size) * num_possible_cpus()); + + SMP_ALIGN(tmp.size) * + (highest_possible_processor_id()+1)); if (!newinfo) return -ENOMEM; @@ -1158,7 +1161,8 @@ int arpt_register_table(struct arpt_table *table, = { 0, 0, 0, { 0 }, { 0 }, { } }; newinfo = vmalloc(sizeof(struct arpt_table_info) - + SMP_ALIGN(repl->size) * num_possible_cpus()); + + SMP_ALIGN(repl->size) * + (highest_possible_processor_id()+1)); if (!newinfo) { ret = -ENOMEM; return ret; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index eef99a1..75c27e9 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -921,8 +922,10 @@ translate_table(const char *name, } /* And one copy for every other CPU */ - for (i = 1; i < num_possible_cpus(); i++) { - memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, + for_each_cpu(i) { + if (i == 0) + continue; + memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i, newinfo->entries, SMP_ALIGN(newinfo->size)); } @@ -943,7 +946,7 @@ replace_table(struct ipt_table *table, struct ipt_entry *table_base; unsigned int i; - for (i = 0; i < num_possible_cpus(); i++) { + for_each_cpu(i) { table_base = (void *)newinfo->entries + TABLE_OFFSET(newinfo, i); @@ -990,7 +993,7 @@ get_counters(const struct ipt_table_info *t, unsigned int cpu; unsigned int i; - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { + for_each_cpu(cpu) { i = 0; IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), t->size, @@ -1128,7 +1131,8 @@ do_replace(void __user *user, unsigned int len) return -ENOMEM; newinfo = vmalloc(sizeof(struct ipt_table_info) - + SMP_ALIGN(tmp.size) * num_possible_cpus()); + + SMP_ALIGN(tmp.size) * + (highest_possible_processor_id()+1)); if (!newinfo) return -ENOMEM; @@ -1458,7 +1462,8 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) = { 0, 0, 0, { 0 }, { 0 }, { } }; newinfo = vmalloc(sizeof(struct ipt_table_info) - + SMP_ALIGN(repl->size) * num_possible_cpus()); + + SMP_ALIGN(repl->size) * + (highest_possible_processor_id()+1)); if (!newinfo) return -ENOMEM; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 2da514b..b03e906 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -950,8 +951,10 @@ translate_table(const char *name, } /* And one copy for every other CPU */ - for (i = 1; i < num_possible_cpus(); i++) { - memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, + for_each_cpu(i) { + if (i == 0) + continue; + memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i, newinfo->entries, SMP_ALIGN(newinfo->size)); } @@ -973,6 +976,7 @@ replace_table(struct ip6t_table *table, unsigned int i; for (i = 0; i < num_possible_cpus(); i++) { + for_each_cpu(i) { table_base = (void *)newinfo->entries + TABLE_OFFSET(newinfo, i); @@ -1019,7 +1023,7 @@ get_counters(const struct ip6t_table_info *t, unsigned int cpu; unsigned int i; - for (cpu = 0; cpu < num_possible_cpus(); cpu++) { + for_each_cpu(cpu) { i = 0; IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), t->size, @@ -1153,7 +1157,8 @@ do_replace(void __user *user, unsigned int len) return -ENOMEM; newinfo = vmalloc(sizeof(struct ip6t_table_info) - + SMP_ALIGN(tmp.size) * num_possible_cpus()); + + SMP_ALIGN(tmp.size) * + (highest_possible_processor_id()+1)); if (!newinfo) return -ENOMEM; @@ -1467,7 +1472,8 @@ int ip6t_register_table(struct ip6t_table *table, = { 0, 0, 0, { 0 }, { 0 }, { } }; newinfo = vmalloc(sizeof(struct ip6t_table_info) - + SMP_ALIGN(repl->size) * num_possible_cpus()); + + SMP_ALIGN(repl->size) * + (highest_possible_processor_id()+1)); if (!newinfo) return -ENOMEM; -- cgit v0.10.2 From 34cb711ba922f53cca45443b8c3c1078873cf599 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 13 Oct 2005 14:41:44 -0700 Subject: [NET]: Disable NET_SCH_CLK_CPU for SMP x86 hosts Opterons with frequency scaling have fully unsynchronized TSCs running at different frequencies, so using TSCs there is not a good idea. Also some other x86 boxes have this problem. gettimeofday should be good enough, so just disable it. Signed-off-by: Andi Kleen Signed-off-by: David S. Miller diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 45d3bc0..81510da 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -72,9 +72,11 @@ config NET_SCH_CLK_GETTIMEOFDAY Choose this if you need a high resolution clock source but can't use the CPU's cycle counter. +# don't allow on SMP x86 because they can have unsynchronized TSCs. +# gettimeofday is a good alternative config NET_SCH_CLK_CPU bool "CPU cycle counter" - depends on X86_TSC || X86_64 || ALPHA || SPARC64 || PPC64 || IA64 + depends on ((X86_TSC || X86_64) && !SMP) || ALPHA || SPARC64 || PPC64 || IA64 help Say Y here if you want to use the CPU's cycle counter as clock source. This is a cheap and high resolution clock source, but on some -- cgit v0.10.2 From eb0d6041143fae63410c5622fef96862e6b20933 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Thu, 13 Oct 2005 14:42:04 -0700 Subject: [CONNECTOR]: Update documentation to match reality. Updated documentation to reflect 2.6.14 netlink changes about socket options, multicasting and group number. Please concider for 2.6.14. Signed-off-by: Evgeniy Polyakov Signed-off-by: David S. Miller diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt index 54a0a14b..57a314b 100644 --- a/Documentation/connector/connector.txt +++ b/Documentation/connector/connector.txt @@ -131,3 +131,47 @@ Netlink itself is not reliable protocol, that means that messages can be lost due to memory pressure or process' receiving queue overflowed, so caller is warned must be prepared. That is why struct cn_msg [main connector's message header] contains u32 seq and u32 ack fields. + +/*****************************************/ +Userspace usage. +/*****************************************/ +2.6.14 has a new netlink socket implementation, which by default does not +allow to send data to netlink groups other than 1. +So, if to use netlink socket (for example using connector) +with different group number userspace application must subscribe to +that group. It can be achieved by following pseudocode: + +s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + +l_local.nl_family = AF_NETLINK; +l_local.nl_groups = 12345; +l_local.nl_pid = 0; + +if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { + perror("bind"); + close(s); + return -1; +} + +{ + int on = l_local.nl_groups; + setsockopt(s, 270, 1, &on, sizeof(on)); +} + +Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket +option. To drop multicast subscription one should call above socket option +with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0. + +2.6.14 netlink code only allows to select a group which is less or equal to +the maximum group number, which is used at netlink_kernel_create() time. +In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use +group number 12345, you must increment CN_NETLINK_USERS to that number. +Additional 0xf numbers are allocated to be used by non-in-kernel users. + +Due to this limitation, group 0xffffffff does not work now, so one can +not use add/remove connector's group notifications, but as far as I know, +only cn_test.c test module used it. + +Some work in netlink area is still being done, so things can be changed in +2.6.15 timeframe, if it will happen, documentation will be updated for that +kernel. -- cgit v0.10.2 From 046d20b73960b7a2474b6d5e920d54c3fd7c23fe Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 13 Oct 2005 14:42:24 -0700 Subject: [TCP]: Ratelimit debugging warning. Better safe than sorry. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f37a50e..7114031 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -436,11 +436,13 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss u16 flags; if (unlikely(len >= skb->len)) { - printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, " - "end_seq=%u, skb->len=%u.\n", len, mss_now, - TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, - skb->len); - WARN_ON(1); + if (net_ratelimit()) { + printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, " + "end_seq=%u, skb->len=%u.\n", len, mss_now, + TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, + skb->len); + WARN_ON(1); + } return 0; } -- cgit v0.10.2 From 51e8513615ed8202b22ba9a43b0c7376ea4f6868 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 13 Oct 2005 21:10:08 -0700 Subject: [SPARC64]: Consolidate common PCI IOMMU init code. All the PCI controller drivers were doing the same thing setting up the IOMMU software state, put it all in one spot. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 425c60c..cdee7d9 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -80,13 +80,59 @@ static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) iopte_val(*iopte) = val; } -void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize) +void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) { - int i; + unsigned long i, tsbbase, order; + + /* Setup initial software IOMMU state. */ + spin_lock_init(&iommu->lock); + iommu->ctx_lowest_free = 1; + iommu->page_table_map_base = dma_offset; + iommu->dma_addr_mask = dma_addr_mask; + + switch (tsbsize / (8 * 1024)) { + case 64: + iommu->page_table_sz_bits = 16; + break; + case 128: + iommu->page_table_sz_bits = 17; + break; + default: + prom_printf("PCI_IOMMU: Illegal TSB size %d\n", + tsbsize / (8 * 1024)); + prom_halt(); + break; + }; + + iommu->lowest_consistent_map = + 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); + + for (i = 0; i < PBM_NCLUSTERS; i++) { + iommu->alloc_info[i].flush = 0; + iommu->alloc_info[i].next = 0; + } - tsbsize /= sizeof(iopte_t); + /* Allocate and initialize the dummy page which we + * set inactive IO PTEs to point to. + */ + iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + if (!iommu->dummy_page) { + prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n"); + prom_halt(); + } + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); + iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); + + /* Now allocate and setup the IOMMU page table itself. */ + order = get_order(tsbsize); + tsbbase = __get_free_pages(GFP_KERNEL, order); + if (!tsbbase) { + prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n"); + prom_halt(); + } + iommu->page_table = (iopte_t *)tsbbase; - for (i = 0; i < tsbsize; i++) + for (i = 0; i < tsbsize / sizeof(iopte_t); i++) iopte_make_dummy(iommu, &iommu->page_table[i]); } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 6ed1ef2..c03ed5f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1207,13 +1207,9 @@ static void psycho_scan_bus(struct pci_controller_info *p) static void psycho_iommu_init(struct pci_controller_info *p) { struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long tsbbase, i; + unsigned long i; u64 control; - /* Setup initial software IOMMU state. */ - spin_lock_init(&iommu->lock); - iommu->ctx_lowest_free = 1; - /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL; iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE; @@ -1240,40 +1236,10 @@ static void psycho_iommu_init(struct pci_controller_info *p) /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ + pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); - iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); - if (!iommu->dummy_page) { - prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); - prom_halt(); - } - memset((void *)iommu->dummy_page, 0, PAGE_SIZE); - iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); - - /* Using assumed page size 8K with 128K entries we need 1MB iommu page - * table (128K ioptes * 8 bytes per iopte). This is - * page order 7 on UltraSparc. - */ - tsbbase = __get_free_pages(GFP_KERNEL, get_order(IO_TSB_SIZE)); - if (!tsbbase) { - prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n"); - prom_halt(); - } - iommu->page_table = (iopte_t *)tsbbase; - iommu->page_table_sz_bits = 17; - iommu->page_table_map_base = 0xc0000000; - iommu->dma_addr_mask = 0xffffffff; - pci_iommu_table_init(iommu, IO_TSB_SIZE); - - /* We start with no consistent mappings. */ - iommu->lowest_consistent_map = - 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); - - for (i = 0; i < PBM_NCLUSTERS; i++) { - iommu->alloc_info[i].flush = 0; - iommu->alloc_info[i].next = 0; - } - - psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase)); + psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, + __pa(iommu->page_table)); control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL); control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); @@ -1281,7 +1247,7 @@ static void psycho_iommu_init(struct pci_controller_info *p) psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control); /* If necessary, hook us up for starfire IRQ translations. */ - if(this_is_starfire) + if (this_is_starfire) p->starfire_cookie = starfire_hookup(p->pbm_A.portid); else p->starfire_cookie = NULL; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 0ee6bd5..da8e136 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1267,13 +1267,9 @@ static void sabre_iommu_init(struct pci_controller_info *p, u32 dma_mask) { struct pci_iommu *iommu = p->pbm_A.iommu; - unsigned long tsbbase, i, order; + unsigned long i; u64 control; - /* Setup initial software IOMMU state. */ - spin_lock_init(&iommu->lock); - iommu->ctx_lowest_free = 1; - /* Register addresses. */ iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL; iommu->iommu_tsbbase = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE; @@ -1295,26 +1291,10 @@ static void sabre_iommu_init(struct pci_controller_info *p, /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ + pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask); - iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); - if (!iommu->dummy_page) { - prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); - prom_halt(); - } - memset((void *)iommu->dummy_page, 0, PAGE_SIZE); - iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); - - tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8)); - if (!tsbbase) { - prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n"); - prom_halt(); - } - iommu->page_table = (iopte_t *)tsbbase; - iommu->page_table_map_base = dvma_offset; - iommu->dma_addr_mask = dma_mask; - pci_iommu_table_init(iommu, PAGE_SIZE << order); - - sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase)); + sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, + __pa(iommu->page_table)); control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL); control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); @@ -1322,11 +1302,9 @@ static void sabre_iommu_init(struct pci_controller_info *p, switch(tsbsize) { case 64: control |= SABRE_IOMMU_TSBSZ_64K; - iommu->page_table_sz_bits = 16; break; case 128: control |= SABRE_IOMMU_TSBSZ_128K; - iommu->page_table_sz_bits = 17; break; default: prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); @@ -1334,15 +1312,6 @@ static void sabre_iommu_init(struct pci_controller_info *p, break; } sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); - - /* We start with no consistent mappings. */ - iommu->lowest_consistent_map = - 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); - - for (i = 0; i < PBM_NCLUSTERS; i++) { - iommu->alloc_info[i].flush = 0; - iommu->alloc_info[i].next = 0; - } } static void pbm_register_toplevel_resources(struct pci_controller_info *p, diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index cae5b61..d8c4e09 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1765,7 +1765,7 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) { struct pci_iommu *iommu = pbm->iommu; - unsigned long tsbbase, i, tagbase, database, order; + unsigned long i, tagbase, database; u32 vdma[2], dma_mask; u64 control; int err, tsbsize; @@ -1800,10 +1800,6 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) prom_halt(); }; - /* Setup initial software IOMMU state. */ - spin_lock_init(&iommu->lock); - iommu->ctx_lowest_free = 1; - /* Register addresses, SCHIZO has iommu ctx flushing. */ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE; @@ -1832,56 +1828,9 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm) /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ + pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); - iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); - if (!iommu->dummy_page) { - prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n"); - prom_halt(); - } - memset((void *)iommu->dummy_page, 0, PAGE_SIZE); - iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); - - /* Using assumed page size 8K with 128K entries we need 1MB iommu page - * table (128K ioptes * 8 bytes per iopte). This is - * page order 7 on UltraSparc. - */ - order = get_order(tsbsize * 8 * 1024); - tsbbase = __get_free_pages(GFP_KERNEL, order); - if (!tsbbase) { - prom_printf("%s: Error, gfp(tsb) failed.\n", pbm->name); - prom_halt(); - } - - iommu->page_table = (iopte_t *)tsbbase; - iommu->page_table_map_base = vdma[0]; - iommu->dma_addr_mask = dma_mask; - pci_iommu_table_init(iommu, PAGE_SIZE << order); - - switch (tsbsize) { - case 64: - iommu->page_table_sz_bits = 16; - break; - - case 128: - iommu->page_table_sz_bits = 17; - break; - - default: - prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); - prom_halt(); - break; - }; - - /* We start with no consistent mappings. */ - iommu->lowest_consistent_map = - 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); - - for (i = 0; i < PBM_NCLUSTERS; i++) { - iommu->alloc_info[i].flush = 0; - iommu->alloc_info[i].next = 0; - } - - schizo_write(iommu->iommu_tsbbase, __pa(tsbbase)); + schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); control = schizo_read(iommu->iommu_control); control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 38bbbcc..c067407 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -102,7 +102,7 @@ struct pci_iommu { u32 dma_addr_mask; }; -extern void pci_iommu_table_init(struct pci_iommu *, int); +extern void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask); /* This describes a PCI bus module's streaming buffer. */ struct pci_strbuf { -- cgit v0.10.2 From 688cb30bdc3e398d97682a6a58f825821ee838c2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 13 Oct 2005 22:15:24 -0700 Subject: [SPARC64]: Eliminate PCI IOMMU dma mapping size limit. The hairy fast allocator in the sparc64 PCI IOMMU code has a hard limit of 256 pages. Certain devices can exceed this when performing very large I/Os. So replace with a more simple allocator, based largely upon the arch/ppc64/kernel/iommu.c code. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index cdee7d9..a11910b 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -49,12 +49,6 @@ static void __iommu_flushall(struct pci_iommu *iommu) /* Ensure completion of previous PIO writes. */ (void) pci_iommu_read(iommu->write_complete_reg); - - /* Now update everyone's flush point. */ - for (entry = 0; entry < PBM_NCLUSTERS; entry++) { - iommu->alloc_info[entry].flush = - iommu->alloc_info[entry].next; - } } #define IOPTE_CONSISTENT(CTX) \ @@ -80,9 +74,61 @@ static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte) iopte_val(*iopte) = val; } +/* Based largely upon the ppc64 iommu allocator. */ +static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages) +{ + struct pci_iommu_arena *arena = &iommu->arena; + unsigned long n, i, start, end, limit; + int pass; + + limit = arena->limit; + start = arena->hint; + pass = 0; + +again: + n = find_next_zero_bit(arena->map, limit, start); + end = n + npages; + if (unlikely(end >= limit)) { + if (likely(pass < 1)) { + limit = start; + start = 0; + __iommu_flushall(iommu); + pass++; + goto again; + } else { + /* Scanned the whole thing, give up. */ + return -1; + } + } + + for (i = n; i < end; i++) { + if (test_bit(i, arena->map)) { + start = i + 1; + goto again; + } + } + + for (i = n; i < end; i++) + __set_bit(i, arena->map); + + arena->hint = end; + + return n; +} + +static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages) +{ + unsigned long i; + + for (i = base; i < (base + npages); i++) + __clear_bit(i, arena->map); +} + void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask) { - unsigned long i, tsbbase, order; + unsigned long i, tsbbase, order, sz, num_tsb_entries; + + num_tsb_entries = tsbsize / sizeof(iopte_t); /* Setup initial software IOMMU state. */ spin_lock_init(&iommu->lock); @@ -90,27 +136,16 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, iommu->page_table_map_base = dma_offset; iommu->dma_addr_mask = dma_addr_mask; - switch (tsbsize / (8 * 1024)) { - case 64: - iommu->page_table_sz_bits = 16; - break; - case 128: - iommu->page_table_sz_bits = 17; - break; - default: - prom_printf("PCI_IOMMU: Illegal TSB size %d\n", - tsbsize / (8 * 1024)); + /* Allocate and initialize the free area map. */ + sz = num_tsb_entries / 8; + sz = (sz + 7UL) & ~7UL; + iommu->arena.map = kmalloc(sz, GFP_KERNEL); + if (!iommu->arena.map) { + prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); prom_halt(); - break; - }; - - iommu->lowest_consistent_map = - 1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS); - - for (i = 0; i < PBM_NCLUSTERS; i++) { - iommu->alloc_info[i].flush = 0; - iommu->alloc_info[i].next = 0; } + memset(iommu->arena.map, 0, sz); + iommu->arena.limit = num_tsb_entries; /* Allocate and initialize the dummy page which we * set inactive IO PTEs to point to. @@ -132,114 +167,24 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, } iommu->page_table = (iopte_t *)tsbbase; - for (i = 0; i < tsbsize / sizeof(iopte_t); i++) + for (i = 0; i < num_tsb_entries; i++) iopte_make_dummy(iommu, &iommu->page_table[i]); } -static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages) +static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages) { - iopte_t *iopte, *limit, *first; - unsigned long cnum, ent, flush_point; - - cnum = 0; - while ((1UL << cnum) < npages) - cnum++; - iopte = (iommu->page_table + - (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); - - if (cnum == 0) - limit = (iommu->page_table + - iommu->lowest_consistent_map); - else - limit = (iopte + - (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); + long entry; - iopte += ((ent = iommu->alloc_info[cnum].next) << cnum); - flush_point = iommu->alloc_info[cnum].flush; - - first = iopte; - for (;;) { - if (IOPTE_IS_DUMMY(iommu, iopte)) { - if ((iopte + (1 << cnum)) >= limit) - ent = 0; - else - ent = ent + 1; - iommu->alloc_info[cnum].next = ent; - if (ent == flush_point) - __iommu_flushall(iommu); - break; - } - iopte += (1 << cnum); - ent++; - if (iopte >= limit) { - iopte = (iommu->page_table + - (cnum << - (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); - ent = 0; - } - if (ent == flush_point) - __iommu_flushall(iommu); - if (iopte == first) - goto bad; - } - - /* I've got your streaming cluster right here buddy boy... */ - return iopte; + entry = pci_arena_alloc(iommu, npages); + if (unlikely(entry < 0)) + return NULL; -bad: - printk(KERN_EMERG "pci_iommu: alloc_streaming_cluster of npages(%ld) failed!\n", - npages); - return NULL; + return iommu->page_table + entry; } -static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, - unsigned long npages, unsigned long ctx) +static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages) { - unsigned long cnum, ent; - - cnum = 0; - while ((1UL << cnum) < npages) - cnum++; - - ent = (base << (32 - IO_PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits)) - >> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits); - - /* If the global flush might not have caught this entry, - * adjust the flush point such that we will flush before - * ever trying to reuse it. - */ -#define between(X,Y,Z) (((Z) - (Y)) >= ((X) - (Y))) - if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush)) - iommu->alloc_info[cnum].flush = ent; -#undef between -} - -/* We allocate consistent mappings from the end of cluster zero. */ -static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long npages) -{ - iopte_t *iopte; - - iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)); - while (iopte > iommu->page_table) { - iopte--; - if (IOPTE_IS_DUMMY(iommu, iopte)) { - unsigned long tmp = npages; - - while (--tmp) { - iopte--; - if (!IOPTE_IS_DUMMY(iommu, iopte)) - break; - } - if (tmp == 0) { - u32 entry = (iopte - iommu->page_table); - - if (entry < iommu->lowest_consistent_map) - iommu->lowest_consistent_map = entry; - return iopte; - } - } - } - return NULL; + pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages); } static int iommu_alloc_ctx(struct pci_iommu *iommu) @@ -279,7 +224,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad struct pcidev_cookie *pcp; struct pci_iommu *iommu; iopte_t *iopte; - unsigned long flags, order, first_page, ctx; + unsigned long flags, order, first_page; void *ret; int npages; @@ -297,9 +242,10 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad iommu = pcp->pbm->iommu; spin_lock_irqsave(&iommu->lock, flags); - iopte = alloc_consistent_cluster(iommu, size >> IO_PAGE_SHIFT); - if (iopte == NULL) { - spin_unlock_irqrestore(&iommu->lock, flags); + iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT); + spin_unlock_irqrestore(&iommu->lock, flags); + + if (unlikely(iopte == NULL)) { free_pages(first_page, order); return NULL; } @@ -308,31 +254,15 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad ((iopte - iommu->page_table) << IO_PAGE_SHIFT)); ret = (void *) first_page; npages = size >> IO_PAGE_SHIFT; - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = iommu_alloc_ctx(iommu); first_page = __pa(first_page); while (npages--) { - iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) | + iopte_val(*iopte) = (IOPTE_CONSISTENT(0UL) | IOPTE_WRITE | (first_page & IOPTE_PAGE)); iopte++; first_page += IO_PAGE_SIZE; } - { - int i; - u32 daddr = *dma_addrp; - - npages = size >> IO_PAGE_SHIFT; - for (i = 0; i < npages; i++) { - pci_iommu_write(iommu->iommu_flush, daddr); - daddr += IO_PAGE_SIZE; - } - } - - spin_unlock_irqrestore(&iommu->lock, flags); - return ret; } @@ -342,7 +272,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ struct pcidev_cookie *pcp; struct pci_iommu *iommu; iopte_t *iopte; - unsigned long flags, order, npages, i, ctx; + unsigned long flags, order, npages; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; pcp = pdev->sysdata; @@ -352,46 +282,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ spin_lock_irqsave(&iommu->lock, flags); - if ((iopte - iommu->page_table) == - iommu->lowest_consistent_map) { - iopte_t *walk = iopte + npages; - iopte_t *limit; - - limit = (iommu->page_table + - (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS))); - while (walk < limit) { - if (!IOPTE_IS_DUMMY(iommu, walk)) - break; - walk++; - } - iommu->lowest_consistent_map = - (walk - iommu->page_table); - } - - /* Data for consistent mappings cannot enter the streaming - * buffers, so we only need to update the TSB. We flush - * the IOMMU here as well to prevent conflicts with the - * streaming mapping deferred tlb flush scheme. - */ - - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL; - - for (i = 0; i < npages; i++, iopte++) - iopte_make_dummy(iommu, iopte); - - if (iommu->iommu_ctxflush) { - pci_iommu_write(iommu->iommu_ctxflush, ctx); - } else { - for (i = 0; i < npages; i++) { - u32 daddr = dvma + (i << IO_PAGE_SHIFT); - - pci_iommu_write(iommu->iommu_flush, daddr); - } - } - - iommu_free_ctx(iommu, ctx); + free_npages(iommu, dvma, npages); spin_unlock_irqrestore(&iommu->lock, flags); @@ -418,25 +309,27 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - if (direction == PCI_DMA_NONE) - BUG(); + if (unlikely(direction == PCI_DMA_NONE)) + goto bad_no_ctx; oaddr = (unsigned long)ptr; npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK); npages >>= IO_PAGE_SHIFT; spin_lock_irqsave(&iommu->lock, flags); + base = alloc_npages(iommu, npages); + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = iommu_alloc_ctx(iommu); + spin_unlock_irqrestore(&iommu->lock, flags); - base = alloc_streaming_cluster(iommu, npages); - if (base == NULL) + if (unlikely(!base)) goto bad; + bus_addr = (iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT)); ret = bus_addr | (oaddr & ~IO_PAGE_MASK); base_paddr = __pa(oaddr & IO_PAGE_MASK); - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = iommu_alloc_ctx(iommu); if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else @@ -447,12 +340,13 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE) iopte_val(*base) = iopte_protection | base_paddr; - spin_unlock_irqrestore(&iommu->lock, flags); - return ret; bad: - spin_unlock_irqrestore(&iommu->lock, flags); + iommu_free_ctx(iommu, ctx); +bad_no_ctx: + if (printk_ratelimit()) + WARN_ON(1); return PCI_DMA_ERROR_CODE; } @@ -527,10 +421,13 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int struct pci_iommu *iommu; struct pci_strbuf *strbuf; iopte_t *base; - unsigned long flags, npages, ctx; + unsigned long flags, npages, ctx, i; - if (direction == PCI_DMA_NONE) - BUG(); + if (unlikely(direction == PCI_DMA_NONE)) { + if (printk_ratelimit()) + WARN_ON(1); + return; + } pcp = pdev->sysdata; iommu = pcp->pbm->iommu; @@ -556,13 +453,14 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int /* Step 1: Kick data out of streaming buffers if necessary. */ if (strbuf->strbuf_enabled) - pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); + pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, + npages, direction); - /* Step 2: Clear out first TSB entry. */ - iopte_make_dummy(iommu, base); + /* Step 2: Clear out TSB entries. */ + for (i = 0; i < npages; i++) + iopte_make_dummy(iommu, base + i); - free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, - npages, ctx); + free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); iommu_free_ctx(iommu, ctx); @@ -667,6 +565,8 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int pci_map_single(pdev, (page_address(sglist->page) + sglist->offset), sglist->length, direction); + if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE)) + return 0; sglist->dma_length = sglist->length; return 1; } @@ -675,21 +575,29 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int iommu = pcp->pbm->iommu; strbuf = &pcp->pbm->stc; - if (direction == PCI_DMA_NONE) - BUG(); + if (unlikely(direction == PCI_DMA_NONE)) + goto bad_no_ctx; /* Step 1: Prepare scatter list. */ npages = prepare_sg(sglist, nelems); - /* Step 2: Allocate a cluster. */ + /* Step 2: Allocate a cluster and context, if necessary. */ spin_lock_irqsave(&iommu->lock, flags); - base = alloc_streaming_cluster(iommu, npages); + base = alloc_npages(iommu, npages); + ctx = 0; + if (iommu->iommu_ctxflush) + ctx = iommu_alloc_ctx(iommu); + + spin_unlock_irqrestore(&iommu->lock, flags); + if (base == NULL) goto bad; - dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << IO_PAGE_SHIFT); + + dma_base = iommu->page_table_map_base + + ((base - iommu->page_table) << IO_PAGE_SHIFT); /* Step 3: Normalize DMA addresses. */ used = nelems; @@ -702,30 +610,28 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int } used = nelems - used; - /* Step 4: Choose a context if necessary. */ - ctx = 0; - if (iommu->iommu_ctxflush) - ctx = iommu_alloc_ctx(iommu); - - /* Step 5: Create the mappings. */ + /* Step 4: Create the mappings. */ if (strbuf->strbuf_enabled) iopte_protection = IOPTE_STREAMING(ctx); else iopte_protection = IOPTE_CONSISTENT(ctx); if (direction != PCI_DMA_TODEVICE) iopte_protection |= IOPTE_WRITE; - fill_sg (base, sglist, used, nelems, iopte_protection); + + fill_sg(base, sglist, used, nelems, iopte_protection); + #ifdef VERIFY_SG verify_sglist(sglist, nelems, base, npages); #endif - spin_unlock_irqrestore(&iommu->lock, flags); - return used; bad: - spin_unlock_irqrestore(&iommu->lock, flags); - return PCI_DMA_ERROR_CODE; + iommu_free_ctx(iommu, ctx); +bad_no_ctx: + if (printk_ratelimit()) + WARN_ON(1); + return 0; } /* Unmap a set of streaming mode DMA translations. */ @@ -738,8 +644,10 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, unsigned long flags, ctx, i, npages; u32 bus_addr; - if (direction == PCI_DMA_NONE) - BUG(); + if (unlikely(direction == PCI_DMA_NONE)) { + if (printk_ratelimit()) + WARN_ON(1); + } pcp = pdev->sysdata; iommu = pcp->pbm->iommu; @@ -751,7 +659,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, if (sglist[i].dma_length == 0) break; i--; - npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT; + npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - + bus_addr) >> IO_PAGE_SHIFT; base = iommu->page_table + ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT); @@ -772,11 +681,11 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, if (strbuf->strbuf_enabled) pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction); - /* Step 2: Clear out first TSB entry. */ - iopte_make_dummy(iommu, base); + /* Step 2: Clear out the TSB entries. */ + for (i = 0; i < npages; i++) + iopte_make_dummy(iommu, base + i); - free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, - npages, ctx); + free_npages(iommu, bus_addr - iommu->page_table_map_base, npages); iommu_free_ctx(iommu, ctx); diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index c067407..dd35a2c 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h @@ -27,23 +27,27 @@ * PCI bus. */ -#define PBM_LOGCLUSTERS 3 -#define PBM_NCLUSTERS (1 << PBM_LOGCLUSTERS) - struct pci_controller_info; /* This contains the software state necessary to drive a PCI * controller's IOMMU. */ +struct pci_iommu_arena { + unsigned long *map; + unsigned int hint; + unsigned int limit; +}; + struct pci_iommu { /* This protects the controller's IOMMU and all * streaming buffers underneath. */ spinlock_t lock; + struct pci_iommu_arena arena; + /* IOMMU page table, a linear array of ioptes. */ iopte_t *page_table; /* The page table itself. */ - int page_table_sz_bits; /* log2 of ow many pages does it map? */ /* Base PCI memory space address where IOMMU mappings * begin. @@ -62,12 +66,6 @@ struct pci_iommu { */ unsigned long write_complete_reg; - /* The lowest used consistent mapping entry. Since - * we allocate consistent maps out of cluster 0 this - * is relative to the beginning of closter 0. - */ - u32 lowest_consistent_map; - /* In order to deal with some buggy third-party PCI bridges that * do wrong prefetching, we never mark valid mappings as invalid. * Instead we point them at this dummy page. @@ -75,16 +73,6 @@ struct pci_iommu { unsigned long dummy_page; unsigned long dummy_page_pa; - /* If PBM_NCLUSTERS is ever decreased to 4 or lower, - * or if largest supported page_table_sz * 8K goes above - * 2GB, you must increase the size of the type of - * these counters. You have been duly warned. -DaveM - */ - struct { - u16 next; - u16 flush; - } alloc_info[PBM_NCLUSTERS]; - /* CTX allocation. */ unsigned long ctx_lowest_free; unsigned long ctx_bitmap[IOMMU_NUM_CTXS / (sizeof(unsigned long) * 8)]; -- cgit v0.10.2 From 6205d158d16d2619bf30f0aff47a8e09b07106e9 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 14 Oct 2005 12:24:24 +0100 Subject: [ARM] 3009/1: S3C2410 - io.h offsets too large for LDRH/STRH Patch from Ben Dooks The __inwc/__outwc calls are capable of creating LDRH and STRH instructions with offsets over 8bits as GCC does not have a constraint for an 8bit offset. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h index 418233a..4bf272e 100644 --- a/include/asm-arm/arch-s3c2410/io.h +++ b/include/asm-arm/arch-s3c2410/io.h @@ -9,7 +9,7 @@ * 06-Dec-1997 RMK Created. * 02-Sep-2003 BJD Modified for S3C2410 * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA - * + * 13-Oct-2005 BJD Fixed problems with LDRH/STRH offset range */ #ifndef __ASM_ARM_ARCH_IO_H @@ -97,7 +97,7 @@ DECLARE_IO(int,l,"") else \ __asm__ __volatile__( \ "strb %0, [%1, #0] @ outbc" \ - : : "r" (value), "r" ((port))); \ + : : "r" (value), "r" ((port))); \ }) #define __inbc(port) \ @@ -110,35 +110,61 @@ DECLARE_IO(int,l,"") else \ __asm__ __volatile__( \ "ldrb %0, [%1, #0] @ inbc" \ - : "=r" (result) : "r" ((port))); \ + : "=r" (result) : "r" ((port))); \ result; \ }) #define __outwc(value,port) \ ({ \ unsigned long v = value; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "strh %0, [%1, %2] @ outwc" \ - : : "r" (v), "r" (PCIO_BASE), "Jr" ((port))); \ - else \ + if (__PORT_PCIO((port))) { \ + if ((port) < 256 && (port) > -256) \ + __asm__ __volatile__( \ + "strh %0, [%1, %2] @ outwc" \ + : : "r" (v), "r" (PCIO_BASE), "Jr" ((port))); \ + else if ((port) > 0) \ + __asm__ __volatile__( \ + "strh %0, [%1, %2] @ outwc" \ + : : "r" (v), \ + "r" (PCIO_BASE + ((port) & ~0xff)), \ + "Jr" (((port) & 0xff))); \ + else \ + __asm__ __volatile__( \ + "strh %0, [%1, #0] @ outwc" \ + : : "r" (v), \ + "r" (PCIO_BASE + (port))); \ + } else \ __asm__ __volatile__( \ "strh %0, [%1, #0] @ outwc" \ - : : "r" (v), "r" ((port))); \ + : : "r" (v), "r" ((port))); \ }) #define __inwc(port) \ ({ \ unsigned short result; \ - if (__PORT_PCIO((port))) \ - __asm__ __volatile__( \ - "ldrh %0, [%1, %2] @ inwc" \ - : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port))); \ - else \ + if (__PORT_PCIO((port))) { \ + if ((port) < 256 && (port) > -256 ) \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2] @ inwc" \ + : "=r" (result) \ + : "r" (PCIO_BASE), \ + "Jr" ((port))); \ + else if ((port) > 0) \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2] @ inwc" \ + : "=r" (result) \ + : "r" (PCIO_BASE + ((port) & ~0xff)), \ + "Jr" (((port) & 0xff))); \ + else \ + __asm__ __volatile__( \ + "ldrh %0, [%1, #0] @ inwc" \ + : "=r" (result) \ + : "r" (PCIO_BASE + ((port)))); \ + } else \ __asm__ __volatile__( \ "ldrh %0, [%1, #0] @ inwc" \ - : "=r" (result) : "r" ((port))); \ - result; \ + : "=r" (result) : "r" ((port))); \ + result; \ }) #define __outlc(value,port) \ -- cgit v0.10.2 From cb90d681ae439e525de9de519508ac9041342321 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Fri, 14 Oct 2005 12:49:15 +0100 Subject: [ARM] 2980/1: Fix L7200 core.c compile Patch from Deepak Saxena This patch fixes L7200 so that it builds in 2.6.latest. I do not have the hardware so don't know if it actually still works, but the changes are fairly trivial. I am not even sure if anyone still maintains, uses, or cares about this machine type. Signed-off-by: Deepak Saxena Signed-off-by: Russell King diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index 5fd8c9f..03ed742 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -7,11 +7,17 @@ */ #include #include +#include +#include +#include +#include #include #include +#include #include +#include /* * IRQ base register @@ -47,6 +53,12 @@ static void l7200_unmask_irq(unsigned int irq) { IRQ_ENABLE = 1 << irq; } + +static struct irqchip l7200_irq_chip = { + .ack = l7200_mask_irq, + .mask = l7200_mask_irq, + .unmask = l7200_unmask_irq +}; static void __init l7200_init_irq(void) { @@ -56,11 +68,9 @@ static void __init l7200_init_irq(void) FIQ_ENABLECLEAR = 0xffffffff; /* clear all fast interrupt enables */ for (irq = 0; irq < NR_IRQS; irq++) { - irq_desc[irq].valid = 1; - irq_desc[irq].probe_ok = 1; - irq_desc[irq].mask_ack = l7200_mask_irq; - irq_desc[irq].mask = l7200_mask_irq; - irq_desc[irq].unmask = l7200_unmask_irq; + set_irq_chip(irq, &l7200_irq_chip); + set_irq_flags(irq, IRQF_VALID); + set_irq_handler(irq, do_level_IRQ); } init_FIQ(); -- cgit v0.10.2 From 04f03bf7dbd04c15c30d91c6a277f6970cc4ef14 Mon Sep 17 00:00:00 2001 From: Baris Cicek Date: Fri, 14 Oct 2005 14:32:40 +0100 Subject: [SERIAL] Add SupraExpress 336i Sp ASVD modem ID Signed-off-by: Russell King diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 6b321e8..c2786fc 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -272,6 +272,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "SUP1421", 0 }, /* SupraExpress 33.6 Data/Fax PnP modem */ { "SUP1590", 0 }, + /* SupraExpress 336i Sp ASVD */ + { "SUP1620", 0 }, /* SupraExpress 33.6 Data/Fax PnP modem */ { "SUP1760", 0 }, /* Phoebe Micro */ -- cgit v0.10.2 From cb38c569e5ecf9e922e66963b6da2751b4f13d81 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 14 Oct 2005 16:07:25 +0100 Subject: [ARM] 3011/1: pxafb: Add ability to set device parent + fix spitz compile error Patch from Richard Purdie Add a function to allow machines to set the parent of the pxa framebuffer device. This means the power up/down sequence can be controlled where required by the machine. Update spitz to use the new function, fixing a compile error. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index d0660a8..d327c12 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -208,6 +208,11 @@ static struct platform_device pxafb_device = { .resource = pxafb_resources, }; +void __init set_pxa_fb_parent(struct device *parent_dev) +{ + pxafb_device.dev.parent = parent_dev; +} + static struct platform_device ffuart_device = { .name = "pxa2xx-uart", .id = 0, diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 568afe3..7eaeb24 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -328,7 +328,7 @@ static void __init common_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); pxa_set_mci_info(&spitz_mci_platform_data); - pxafb_device.dev.parent = &spitzssp_device.dev; + set_pxa_fb_parent(&spitzssp_device.dev); set_pxa_fb_info(&spitz_pxafb_info); } diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h index 21c0e16..aba9b30 100644 --- a/include/asm-arm/arch-pxa/pxafb.h +++ b/include/asm-arm/arch-pxa/pxafb.h @@ -66,4 +66,5 @@ struct pxafb_mach_info { }; void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info); +void set_pxa_fb_parent(struct device *parent_dev); unsigned long pxafb_get_hsync_time(struct device *dev); -- cgit v0.10.2 From 10f92eb7c6b4e8069c2defd2ad23b74f31f8962d Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 14 Oct 2005 16:07:26 +0100 Subject: [ARM] 3012/1: Corgi/Spitz LCD: Use bus_find_device to locate pxafb - fix compile error Patch from Richard Purdie Update corgi_lcd to use bus_find_device to locate the pxafb device hence fixing a compile error. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c index c02ef7c..850538f 100644 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ b/arch/arm/mach-pxa/corgi_lcd.c @@ -467,6 +467,7 @@ void corgi_put_hsync(void) { if (get_hsync_time) symbol_put(w100fb_get_hsynclen); + get_hsync_time = NULL; } void corgi_wait_hsync(void) @@ -476,20 +477,37 @@ void corgi_wait_hsync(void) #endif #ifdef CONFIG_PXA_SHARP_Cxx00 +static struct device *spitz_pxafb_dev; + +static int is_pxafb_device(struct device * dev, void * data) +{ + struct platform_device *pdev = container_of(dev, struct platform_device, dev); + + return (strncmp(pdev->name, "pxa2xx-fb", 9) == 0); +} + unsigned long spitz_get_hsync_len(void) { + if (!spitz_pxafb_dev) { + spitz_pxafb_dev = bus_find_device(&platform_bus_type, NULL, NULL, is_pxafb_device); + if (!spitz_pxafb_dev) + return 0; + } if (!get_hsync_time) get_hsync_time = symbol_get(pxafb_get_hsync_time); if (!get_hsync_time) return 0; - return pxafb_get_hsync_time(&pxafb_device.dev); + return pxafb_get_hsync_time(spitz_pxafb_dev); } void spitz_put_hsync(void) { + put_device(spitz_pxafb_dev); if (get_hsync_time) symbol_put(pxafb_get_hsync_time); + spitz_pxafb_dev = NULL; + get_hsync_time = NULL; } void spitz_wait_hsync(void) -- cgit v0.10.2 From 72023b63cc512d2d7c2a31c6bc1be497eafbd834 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 14 Oct 2005 16:07:27 +0100 Subject: [ARM] 3013/1: Spitz: Fix compile errors Patch from Richard Purdie Remove a couple of lines of accidently added code causing compile errors. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 7eaeb24..d0ab428 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -304,7 +303,6 @@ static struct platform_device *devices[] __initdata = { &spitzkbd_device, &spitzts_device, &spitzbl_device, - &spitzbattery_device, }; static void __init common_init(void) -- cgit v0.10.2 From 414894938b88c1ad2e9cea6502ceccefb30605c4 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 14 Oct 2005 16:07:28 +0100 Subject: [ARM] 3014/1: Spitz keyboard: Correct the right shift key Patch from Richard Purdie Correct the right shift key entry in the spitz keyboard driver. Signed-off-by: Richard Purdie Signed-off-by: Russell King diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 1714045..344f460 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -53,7 +53,7 @@ static unsigned char spitzkbd_keycode[NR_SCANCODES] = { KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, /* 49-64 */ + SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ -- cgit v0.10.2 From f75884d28a6eae5a422d0454b982da3842f777af Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 14 Oct 2005 13:44:32 -0700 Subject: [QLOGICPTI]: Handle INQUIRY response sniffing correctly. These days, in 2.6.x, even INQUIRY commands are sent using scatter gather lists. Bug reported by Tom 'spot' Callaway. Signed-off-by: David S. Miller diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index a917ab7..1fd5fc6 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1119,6 +1119,36 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); } +static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) +{ + unsigned char *buf; + unsigned int buflen; + + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buflen = sg->length; + } else { + buf = cmd->request_buffer; + buflen = cmd->request_bufflen; + } + + *buf_out = buf; + return buflen; +} + +static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf) +{ + if (cmd->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) cmd->request_buffer; + kunmap_atomic(buf - sg->offset, KM_IRQ0); + } +} + /* * Until we scan the entire bus with inquiries, go throught this fella... */ @@ -1145,11 +1175,9 @@ static void ourdone(struct scsi_cmnd *Cmnd) int ok = host_byte(Cmnd->result) == DID_OK; if (Cmnd->cmnd[0] == 0x12 && ok) { unsigned char *iqd; + unsigned int iqd_len; - if (Cmnd->use_sg != 0) - BUG(); - - iqd = ((unsigned char *)Cmnd->buffer); + iqd_len = scsi_rbuf_get(Cmnd, &iqd); /* tags handled in midlayer */ /* enable sync mode? */ @@ -1163,6 +1191,9 @@ static void ourdone(struct scsi_cmnd *Cmnd) if (iqd[7] & 0x20) { qpti->dev_param[tgt].device_flags |= 0x20; } + + scsi_rbuf_put(Cmnd, iqd); + qpti->sbits |= (1 << tgt); } else if (!ok) { qpti->sbits |= (1 << tgt); -- cgit v0.10.2 From b4d1b825785847cddee6d104113da913f2ca8efb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 14 Oct 2005 15:26:08 -0700 Subject: [SPARC64]: Fix powering off on SMP. Doing a "SUNW,stop-self" firmware call on the other cpus is not the correct thing to do when dropping into the firmware for a halt, reboot, or power-off. For now, just do nothing to quiet the other cpus, as the system should be quiescent enough. Later we may decide to implement smp_send_stop() like the other SMP platforms do. Based upon a report from Christopher Zimmermann. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 590df5a..b137fd6 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1001,13 +1001,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs) preempt_enable(); } -extern unsigned long xcall_promstop; - -void smp_promstop_others(void) -{ - smp_cross_call(&xcall_promstop, 0, 0, 0); -} - #define prof_multiplier(__cpu) cpu_data(__cpu).multiplier #define prof_counter(__cpu) cpu_data(__cpu).counter diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 058b812..e4c9151 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S @@ -453,22 +453,6 @@ xcall_flush_dcache_page_spitfire: /* %g1 == physical page address nop nop - .globl xcall_promstop -xcall_promstop: - rdpr %pstate, %g2 - wrpr %g2, PSTATE_IG | PSTATE_AG, %pstate - rdpr %pil, %g2 - wrpr %g0, 15, %pil - sethi %hi(109f), %g7 - b,pt %xcc, etrap_irq -109: or %g7, %lo(109b), %g7 - flushw - call prom_stopself - nop - /* We should not return, just spin if we do... */ -1: b,a,pt %xcc, 1b - nop - .data errata32_hwbug: diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index 9b895fa..87f5cfc 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c @@ -68,19 +68,11 @@ void prom_cmdline(void) local_irq_restore(flags); } -#ifdef CONFIG_SMP -extern void smp_promstop_others(void); -#endif - /* Drop into the prom, but completely terminate the program. * No chance of continuing. */ void prom_halt(void) { -#ifdef CONFIG_SMP - smp_promstop_others(); - udelay(8000); -#endif again: p1275_cmd("exit", P1275_INOUT(0, 0)); goto again; /* PROM is out to get me -DaveM */ @@ -88,10 +80,6 @@ again: void prom_halt_power_off(void) { -#ifdef CONFIG_SMP - smp_promstop_others(); - udelay(8000); -#endif p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0)); /* if nothing else helps, we just halt */ -- cgit v0.10.2 From 43d2c4ca385b02ab7a604aa09a9da36f1668bee6 Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 14 Oct 2005 15:59:00 -0700 Subject: [PATCH] mips: fix build error in TANBAC TB0226 arch/mips/pci/fixup-tb0226.c: In function `pcibios_map_irq': arch/mips/pci/fixup-tb0226.c:31: warning: implicit declaration of function `vr41xx_set_irq_trigger' arch/mips/pci/fixup-tb0226.c:32: error: `TRIGGER_LEVEL' undeclared (first use in this function) arch/mips/pci/fixup-tb0226.c:32: error: (Each undeclared identifier is reported only once arch/mips/pci/fixup-tb0226.c:32: error: for each function it appears in.) arch/mips/pci/fixup-tb0226.c:33: error: `SIGNAL_THROUGH' undeclared (first use in this function) arch/mips/pci/fixup-tb0226.c:34: warning: implicit declaration of function `vr41xx_set_irq_level' arch/mips/pci/fixup-tb0226.c:34: error: `LEVEL_LOW' undeclared (first use in this function) Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c index 61513d5..b5d42b1 100644 --- a/arch/mips/pci/fixup-tb0226.c +++ b/arch/mips/pci/fixup-tb0226.c @@ -1,7 +1,7 @@ /* * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups. * - * Copyright (C) 2002-2004 Yoichi Yuasa + * Copyright (C) 2002-2005 Yoichi Yuasa * * 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 @@ -20,6 +20,7 @@ #include #include +#include #include int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) @@ -29,42 +30,42 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) switch (slot) { case 12: vr41xx_set_irq_trigger(GD82559_1_PIN, - TRIGGER_LEVEL, - SIGNAL_THROUGH); - vr41xx_set_irq_level(GD82559_1_PIN, LEVEL_LOW); + IRQ_TRIGGER_LEVEL, + IRQ_SIGNAL_THROUGH); + vr41xx_set_irq_level(GD82559_1_PIN, IRQ_LEVEL_LOW); irq = GD82559_1_IRQ; break; case 13: vr41xx_set_irq_trigger(GD82559_2_PIN, - TRIGGER_LEVEL, - SIGNAL_THROUGH); - vr41xx_set_irq_level(GD82559_2_PIN, LEVEL_LOW); + IRQ_TRIGGER_LEVEL, + IRQ_SIGNAL_THROUGH); + vr41xx_set_irq_level(GD82559_2_PIN, IRQ_LEVEL_LOW); irq = GD82559_2_IRQ; break; case 14: switch (pin) { case 1: vr41xx_set_irq_trigger(UPD720100_INTA_PIN, - TRIGGER_LEVEL, - SIGNAL_THROUGH); + IRQ_TRIGGER_LEVEL, + IRQ_SIGNAL_THROUGH); vr41xx_set_irq_level(UPD720100_INTA_PIN, - LEVEL_LOW); + IRQ_LEVEL_LOW); irq = UPD720100_INTA_IRQ; break; case 2: vr41xx_set_irq_trigger(UPD720100_INTB_PIN, - TRIGGER_LEVEL, - SIGNAL_THROUGH); + IRQ_TRIGGER_LEVEL, + IRQ_SIGNAL_THROUGH); vr41xx_set_irq_level(UPD720100_INTB_PIN, - LEVEL_LOW); + IRQ_LEVEL_LOW); irq = UPD720100_INTB_IRQ; break; case 3: vr41xx_set_irq_trigger(UPD720100_INTC_PIN, - TRIGGER_LEVEL, - SIGNAL_THROUGH); + IRQ_TRIGGER_LEVEL, + IRQ_SIGNAL_THROUGH); vr41xx_set_irq_level(UPD720100_INTC_PIN, - LEVEL_LOW); + IRQ_LEVEL_LOW); irq = UPD720100_INTC_IRQ; break; default: -- cgit v0.10.2 From 6edb7467be2195e7eeb6844e37668253af216100 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 14 Oct 2005 15:59:01 -0700 Subject: [PATCH] zaurus: fix compilation with cpufreq disabled This fixes compilation with CPU_FREQ disabled. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index beeec7b..8000890 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -592,6 +592,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, return ret; } +#ifdef CONFIG_CPU_FREQ /* * sa1100fb_display_dma_period() * Calculate the minimum period (in picoseconds) between two DMA @@ -606,6 +607,7 @@ static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo */ return var->pixclock * 8 * 16 / var->bits_per_pixel; } +#endif /* * sa1100fb_check_var(): -- cgit v0.10.2 From 4846d0172dd7fb6a77843644caa6d9a8909225b9 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 14 Oct 2005 15:59:02 -0700 Subject: [PATCH] zaurus: fix soc_common.c This fixes wrong comments, non-working debug subsystem, and some potentially dangerous macros. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 888b70e..9e7ccd8 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -66,7 +66,7 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, if (pc_debug > lvl) { printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func); va_start(args, fmt); - printk(fmt, args); + vprintk(fmt, args); va_end(args); } } @@ -321,8 +321,6 @@ soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) * less punt all of this work and let the kernel handle the details * of power configuration, reset, &c. We also record the value of * `state' in order to regurgitate it to the PCMCIA core later. - * - * Returns: 0 */ static int soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) @@ -407,7 +405,7 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m * the map speed as requested, but override the address ranges * supplied by Card Services. * - * Returns: 0 on success, -1 on error + * Returns: 0 on success, -ERRNO on error */ static int soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) @@ -655,8 +653,8 @@ static void soc_pcmcia_cpufreq_unregister(void) } #else -#define soc_pcmcia_cpufreq_register() -#define soc_pcmcia_cpufreq_unregister() +static int soc_pcmcia_cpufreq_register(void) { return 0; } +static void soc_pcmcia_cpufreq_unregister(void) {} #endif int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) @@ -738,7 +736,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops goto out_err_5; } - if ( list_empty(&soc_pcmcia_sockets) ) + if (list_empty(&soc_pcmcia_sockets)) soc_pcmcia_cpufreq_register(); list_add(&skt->node, &soc_pcmcia_sockets); @@ -839,7 +837,7 @@ int soc_common_drv_pcmcia_remove(struct device *dev) release_resource(&skt->res_io); release_resource(&skt->res_skt); } - if ( list_empty(&soc_pcmcia_sockets) ) + if (list_empty(&soc_pcmcia_sockets)) soc_pcmcia_cpufreq_unregister(); up(&soc_pcmcia_sockets_lock); -- cgit v0.10.2 From 65d406ace3b44e042807d3f9a2e71088818e80f2 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 14 Oct 2005 15:59:03 -0700 Subject: [PATCH] zaurus: fix dependencies on collie keyboard This fixes depenencies of collie keyboard. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 444f775..571a686 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -93,7 +93,7 @@ config KEYBOARD_LKKBD config KEYBOARD_LOCOMO tristate "LoCoMo Keyboard Support" - depends on SHARP_LOCOMO + depends on SHARP_LOCOMO && INPUT_KEYBOARD help Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA -- cgit v0.10.2 From c6ecf7ed3131961e5aeedb0efd217afa0808798f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 14 Oct 2005 15:59:03 -0700 Subject: [PATCH] Add missing export of getnstimeofday() Adds the missing EXPORT_SYMBOL_GPL for getnstimeofday() when CONFIG_TIME_INTERPOLATION isn't set. Needed by drivers/char/mmtimer.c Signed-off-by: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/time.c b/kernel/time.c index dd5ae11..40c2410 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -570,6 +570,7 @@ void getnstimeofday(struct timespec *tv) tv->tv_sec = x.tv_sec; tv->tv_nsec = x.tv_usec * NSEC_PER_USEC; } +EXPORT_SYMBOL_GPL(getnstimeofday); #endif #if (BITS_PER_LONG < 64) -- cgit v0.10.2 From f1ac046d7b297186f755fb213589b539426e1406 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 14 Oct 2005 15:59:04 -0700 Subject: [PATCH] radio-cadet: check request_region() return value correctly Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 022913d..9b04063 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -543,7 +543,7 @@ static int cadet_probe(void) for(i=0;i<8;i++) { io=iovals[i]; - if(request_region(io,2, "cadet-probe")>=0) { + if (request_region(io, 2, "cadet-probe")) { cadet_setfreq(1410); if(cadet_getfreq()==1410) { release_region(io, 2); -- cgit v0.10.2 From e26148d934762b61133a64b6862f870624ff617d Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Fri, 14 Oct 2005 15:59:05 -0700 Subject: [PATCH] Fix copy-and-paste error in BSD accounting Fix copy and paste error in jiffies_to_AHZ conversion which leads to wrong BSD accounting information on alpha and ia64 when CONFIG_BSD_PROCESS_ACCT_V3 is turned on. Also update comment to match reorganised header files. Signed-off-by: Tim Schmielau Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/acct.h b/include/linux/acct.h index 1993a36..19f7046 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -162,13 +162,13 @@ typedef struct acct acct_t; #ifdef __KERNEL__ /* * Yet another set of HZ to *HZ helper functions. - * See for the original. + * See for the original. */ static inline u32 jiffies_to_AHZ(unsigned long x) { #if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0 - return x / (HZ / USER_HZ); + return x / (HZ / AHZ); #else u64 tmp = (u64)x * TICK_NSEC; do_div(tmp, (NSEC_PER_SEC / AHZ)); -- cgit v0.10.2 From 6593b58cfb54138781c5cd88f605e2ae663301b0 Mon Sep 17 00:00:00 2001 From: Matteo Croce <3297627799@wind.it> Date: Fri, 14 Oct 2005 15:59:06 -0700 Subject: [PATCH] wireless/airo: Build fix The aironet PCI driver has a build dependency on ISA that prevent the driver to compile on systems that doesn't support ISA, like x86_64. The driver really doesn't depend on ISA, it does some ISA stuff in the initialization code, since the driver supports both ISA and PCI cards. So the driver should depend on ISA_DMA_API to build on all systems, and this will not hurt PCI at all. Signed-off-by: Matteo Croce <3297627799@wind.it> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 00a07f3..7187958 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -243,7 +243,7 @@ config IPW_DEBUG config AIRO tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on NET_RADIO && ISA && (PCI || BROKEN) + depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN) ---help--- This is the standard Linux driver to support Cisco/Aironet ISA and PCI 802.11 wireless cards. -- cgit v0.10.2 From a90933fb4e7b85587e5cbdf863deeb16695c19bd Mon Sep 17 00:00:00 2001 From: Hirokazu Takata Date: Fri, 14 Oct 2005 15:59:07 -0700 Subject: [PATCH] m32r: Fix smp.c for preempt kernel This patch fixes the following BUG message of arch/m32r/smp.c for CONFIG_DEBUG_PREEMPT: BUG: using smp_processor_id() in preemptible This message is displayed by an smp_processor_id() execution during kernel's preemptible-state. Signed-off-by: Hitoshi Yamamoto Signed-off-by: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c index a4576ac..8b1f6eb 100644 --- a/arch/m32r/kernel/smp.c +++ b/arch/m32r/kernel/smp.c @@ -275,12 +275,14 @@ static void flush_tlb_all_ipi(void *info) *==========================================================================*/ void smp_flush_tlb_mm(struct mm_struct *mm) { - int cpu_id = smp_processor_id(); + int cpu_id; cpumask_t cpu_mask; - unsigned long *mmc = &mm->context[cpu_id]; + unsigned long *mmc; unsigned long flags; preempt_disable(); + cpu_id = smp_processor_id(); + mmc = &mm->context[cpu_id]; cpu_mask = mm->cpu_vm_mask; cpu_clear(cpu_id, cpu_mask); @@ -343,12 +345,14 @@ void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { struct mm_struct *mm = vma->vm_mm; - int cpu_id = smp_processor_id(); + int cpu_id; cpumask_t cpu_mask; - unsigned long *mmc = &mm->context[cpu_id]; + unsigned long *mmc; unsigned long flags; preempt_disable(); + cpu_id = smp_processor_id(); + mmc = &mm->context[cpu_id]; cpu_mask = mm->cpu_vm_mask; cpu_clear(cpu_id, cpu_mask); -- cgit v0.10.2 From 1350843cf0fa46e2f633c78b335777aac3d054b2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 14 Oct 2005 15:59:09 -0700 Subject: [PATCH] ppc64: Fix G5 model in /proc/cpuinfo Andreas Schwab spotted that recent kernels broke reporting of the PowerMac machine model in /proc/cpuinfo. This fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index 2575525..fa8121d 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -115,7 +115,7 @@ static void __pmac pmac_show_cpuinfo(struct seq_file *m) /* find motherboard type */ seq_printf(m, "machine\t\t: "); - np = find_devices("device-tree"); + np = of_find_node_by_path("/"); if (np != NULL) { pp = (char *) get_property(np, "model", NULL); if (pp != NULL) @@ -133,6 +133,7 @@ static void __pmac pmac_show_cpuinfo(struct seq_file *m) } seq_printf(m, "\n"); } + of_node_put(np); } else seq_printf(m, "PowerMac\n"); -- cgit v0.10.2 From 0e7734d3ca24302a513e69dd24a560c34047c038 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Fri, 14 Oct 2005 15:59:10 -0700 Subject: [PATCH] aacraid: host_lock not released fix While doing some testing of error cases I ran into this bug. In some cases the reset handler can exit with the host_lock still held. Signed-off-by: Mark Haverkamp Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index de8490a..a1f9cee 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -453,9 +453,9 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) /* * We can exit If all the commands are complete */ + spin_unlock_irq(host->host_lock); if (active == 0) return SUCCESS; - spin_unlock_irq(host->host_lock); ssleep(1); spin_lock_irq(host->host_lock); } -- cgit v0.10.2 From 2d1f87a728a5ddd9ee0418e14a12e5cb0372fad1 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Fri, 14 Oct 2005 15:59:11 -0700 Subject: [PATCH] Dallas's 1-wire bus compile error drivers/built-in.o: In function `w1_alloc_dev': undefined reference to `netlink_kernel_create' drivers/built-in.o: In function `w1_alloc_dev': undefined reference to `sock_release' Signed-off-by: Evgeniy Polyakov Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 1b6b74c..14016b1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -77,8 +77,7 @@ static void w1_master_release(struct device *dev) dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name); - if (md->nls && md->nls->sk_socket) - sock_release(md->nls->sk_socket); + dev_fini_netlink(md); memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master)); kfree(md); } -- cgit v0.10.2 From 63c6764ce4c650245a41a95a2235207d25ca4fde Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Fri, 14 Oct 2005 15:59:11 -0700 Subject: [PATCH] nommu build error fix "proc_smaps_operations" is not defined in case of "CONFIG_MMU=n". Signed-off-by: Yoshinori Sato Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 3b33f94..a170450 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -103,7 +103,9 @@ enum pid_directory_inos { PROC_TGID_NUMA_MAPS, PROC_TGID_MOUNTS, PROC_TGID_WCHAN, +#ifdef CONFIG_MMU PROC_TGID_SMAPS, +#endif #ifdef CONFIG_SCHEDSTATS PROC_TGID_SCHEDSTAT, #endif @@ -141,7 +143,9 @@ enum pid_directory_inos { PROC_TID_NUMA_MAPS, PROC_TID_MOUNTS, PROC_TID_WCHAN, +#ifdef CONFIG_MMU PROC_TID_SMAPS, +#endif #ifdef CONFIG_SCHEDSTATS PROC_TID_SCHEDSTAT, #endif @@ -195,7 +199,9 @@ static struct pid_entry tgid_base_stuff[] = { E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), +#ifdef CONFIG_MMU E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), +#endif #ifdef CONFIG_SECURITY E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), #endif @@ -235,7 +241,9 @@ static struct pid_entry tid_base_stuff[] = { E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), +#ifdef CONFIG_MMU E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), +#endif #ifdef CONFIG_SECURITY E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), #endif @@ -630,6 +638,7 @@ static struct file_operations proc_numa_maps_operations = { }; #endif +#ifdef CONFIG_MMU extern struct seq_operations proc_pid_smaps_op; static int smaps_open(struct inode *inode, struct file *file) { @@ -648,6 +657,7 @@ static struct file_operations proc_smaps_operations = { .llseek = seq_lseek, .release = seq_release, }; +#endif extern struct seq_operations mounts_op; static int mounts_open(struct inode *inode, struct file *file) @@ -1681,10 +1691,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir, case PROC_TGID_MOUNTS: inode->i_fop = &proc_mounts_operations; break; +#ifdef CONFIG_MMU case PROC_TID_SMAPS: case PROC_TGID_SMAPS: inode->i_fop = &proc_smaps_operations; break; +#endif #ifdef CONFIG_SECURITY case PROC_TID_ATTR: inode->i_nlink = 2; -- cgit v0.10.2 From d656901bca2e19057ca7a6e48bc56dec9ca7003e Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Fri, 14 Oct 2005 15:59:12 -0700 Subject: [PATCH] sh-sci.c sci_start_tx error Argument does not agree. Signed-off-by: Yoshinori Sato Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5122663..430754e 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -967,7 +967,7 @@ static int sci_startup(struct uart_port *port) #endif sci_request_irq(s); - sci_start_tx(port, 1); + sci_start_tx(port); sci_start_rx(port, 1); return 0; -- cgit v0.10.2 From 757e0108473787f470294ce77bf703fedddfce7d Mon Sep 17 00:00:00 2001 From: "Kolli, Neela Syam" Date: Fri, 14 Oct 2005 15:59:13 -0700 Subject: [PATCH] megaraid maintainers entry I am taking over all Megaraid SCSI drivers. Here is the patch for the MAINTENERS file. Signed-off-by: Neela Syam Kolli Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index abf7f7a..767fb61 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1618,6 +1618,13 @@ M: vandrove@vc.cvut.cz L: linux-fbdev-devel@lists.sourceforge.net S: Maintained +MEGARAID SCSI DRIVERS +P: Neela Syam Kolli +M: Neela.Kolli@engenio.com +S: linux-scsi@vger.kernel.org +W: http://megaraid.lsilogic.com +S: Maintained + MEMORY TECHNOLOGY DEVICES P: David Woodhouse M: dwmw2@infradead.org -- cgit v0.10.2 From 7a3ca7d2b5ec31b2cfa594b961d77e68075e33c7 Mon Sep 17 00:00:00 2001 From: Randall Nortman Date: Fri, 14 Oct 2005 17:21:50 -0700 Subject: [PATCH] usbserial: Regression in USB generic serial driver Kernel version 2.6.13 introduced a regression in the generic USB serial converter driver (usbserial.o, drivers/usb/serial/generic.c). The bug manifests, as far as I can tell, whenever you attempt to write to the device -- the write will never complete (write() returns 0, or blocks). Signed-off-by: Randall Nortman Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index ddde5fb..5f7d319 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -223,7 +223,7 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) dbg("%s - port %d", __FUNCTION__, port->number); if (serial->num_bulk_out) { - if (port->write_urb_busy) + if (!(port->write_urb_busy)) room = port->bulk_out_size; } -- cgit v0.10.2 From c1542cbc50d19565006633827532ab9f96c92cea Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Sat, 15 Oct 2005 10:43:35 +0100 Subject: [SERIAL] Add SupraExpress 56i support The modem is said to work with belows addition to pnp_dev_table[]: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=296011 Signed-off-by: maximilian attems Signed-off-by: Russell King diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index c2786fc..5d8660a 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -276,6 +276,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "SUP1620", 0 }, /* SupraExpress 33.6 Data/Fax PnP modem */ { "SUP1760", 0 }, + /* SupraExpress 56i Sp Intl */ + { "SUP2171", 0 }, /* Phoebe Micro */ /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ { "TEX0011", 0 }, -- cgit v0.10.2 From e6850cce8f0fcb0e16b981f13cb9c69618bbdaf1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 15 Oct 2005 16:15:38 -0700 Subject: [NETFILTER]: Fix ip6_table.c build with NETFILTER_DEBUG enabled. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index b03e906..21deec2 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -975,7 +975,6 @@ replace_table(struct ip6t_table *table, struct ip6t_entry *table_base; unsigned int i; - for (i = 0; i < num_possible_cpus(); i++) { for_each_cpu(i) { table_base = (void *)newinfo->entries -- cgit v0.10.2 From 688ce17b8599abc548b406c00e4d18ae0dec954f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Oct 2005 00:17:33 -0700 Subject: [PATCH]: highest_possible_processor_id() has to be a macro ... otherwise, things like alpha and sparc64 break and break badly. They define cpu_possible_map to something else in smp.h *AFTER* having included cpumask.h. If that puppy is a macro, expansion will happen at the actual caller, when we'd already seen #define cpu_possible_map ... and we will get the right thing used. As an inline helper it will be tokenized before we get to that define and that's it; no matter what we define later, it won't affect anything. We get modules with dependency on cpu_possible_map instead of the right symbol (phys_cpu_present_map in case of sparc64), or outright link errors if they are built-in. Signed-off-by: Al Viro Signed-off-by: David S. Miller diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index fe97783..9bdba81 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -393,15 +393,13 @@ extern cpumask_t cpu_present_map; #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) /* Find the highest possible smp_processor_id() */ -static inline unsigned int highest_possible_processor_id(void) -{ - unsigned int cpu, highest = 0; - - for_each_cpu_mask(cpu, cpu_possible_map) - highest = cpu; - - return highest; -} +#define highest_possible_processor_id() \ +({ \ + unsigned int cpu, highest = 0; \ + for_each_cpu_mask(cpu, cpu_possible_map) \ + highest = cpu; \ + highest; \ +}) #endif /* __LINUX_CPUMASK_H */ -- cgit v0.10.2 From 3d80636a0d5f056ffc26472d05b6027a7a9f6e1c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Oct 2005 17:36:06 -0700 Subject: Fix memory ordering bug in page reclaim As noticed by Nick Piggin, we need to make sure that we check the page count before we check for PageDirty, since the dirty check is only valid if the count implies that we're the only possible ones holding the page. We always did do this, but the code needs a read-memory-barrier to make sure that the orderign is also honored by the CPU. (The writer side is ordered due to the atomic decrement and test on the page count, see the discussion on linux-kernel) Signed-off-by: Linus Torvalds diff --git a/mm/vmscan.c b/mm/vmscan.c index 0ea71e8..64f9570 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -511,10 +511,11 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) * PageDirty _after_ making sure that the page is freeable and * not in use by anybody. (pagecache + us == 2) */ - if (page_count(page) != 2 || PageDirty(page)) { - write_unlock_irq(&mapping->tree_lock); - goto keep_locked; - } + if (unlikely(page_count(page) != 2)) + goto cannot_free; + smp_rmb(); + if (unlikely(PageDirty(page))) + goto cannot_free; #ifdef CONFIG_SWAP if (PageSwapCache(page)) { @@ -538,6 +539,10 @@ free_it: __pagevec_release_nonlru(&freed_pvec); continue; +cannot_free: + write_unlock_irq(&mapping->tree_lock); + goto keep_locked; + activate_locked: SetPageActive(page); pgactivate++; -- cgit v0.10.2 From b24d18aa743dad0c42918157c5d717686269d3a8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 16 Oct 2005 20:29:20 -0700 Subject: [PATCH] list: add missing rcu_dereference on first element It seems that all the list_*_rcu primitives are missing a memory barrier on the very first dereference. For example, #define list_for_each_rcu(pos, head) \ for (pos = (head)->next; prefetch(pos->next), pos != (head); \ pos = rcu_dereference(pos->next)) It will go something like: pos = (head)->next prefetch(pos->next) pos != (head) do stuff We're missing a barrier here. pos = rcu_dereference(pos->next) fetch pos->next barrier given by rcu_dereference(pos->next) store pos Without the missing barrier, the pos->next value may turn out to be stale. In fact, if "do stuff" were also dereferencing pos and relying on list_for_each_rcu to provide the barrier then it may also break. So here is a patch to make sure that we have a barrier for the first element in the list. Signed-off-by: Herbert Xu Acked-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/list.h b/include/linux/list.h index e6ec596..084971f 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -442,12 +442,14 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_rcu(pos, head) \ - for (pos = (head)->next; prefetch(pos->next), pos != (head); \ - pos = rcu_dereference(pos->next)) + for (pos = (head)->next; \ + prefetch(rcu_dereference(pos)->next), pos != (head); \ + pos = pos->next) #define __list_for_each_rcu(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = rcu_dereference(pos->next)) + for (pos = (head)->next; \ + rcu_dereference(pos) != (head); \ + pos = pos->next) /** * list_for_each_safe_rcu - iterate over an rcu-protected list safe @@ -461,8 +463,9 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_safe_rcu(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = rcu_dereference(n), n = pos->next) + for (pos = (head)->next; \ + n = rcu_dereference(pos)->next, pos != (head); \ + pos = n) /** * list_for_each_entry_rcu - iterate over rcu list of given type @@ -474,11 +477,11 @@ static inline void list_splice_init(struct list_head *list, * the _rcu list-mutation primitives such as list_add_rcu() * as long as the traversal is guarded by rcu_read_lock(). */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - prefetch(pos->member.next), &pos->member != (head); \ - pos = rcu_dereference(list_entry(pos->member.next, \ - typeof(*pos), member))) +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + prefetch(rcu_dereference(pos)->member.next), \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) /** @@ -492,8 +495,9 @@ static inline void list_splice_init(struct list_head *list, * as long as the traversal is guarded by rcu_read_lock(). */ #define list_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next; prefetch((pos)->next), (pos) != (head); \ - (pos) = rcu_dereference((pos)->next)) + for ((pos) = (pos)->next; \ + prefetch(rcu_dereference((pos))->next), (pos) != (head); \ + (pos) = (pos)->next) /* * Double linked lists with a single pointer list head. @@ -696,8 +700,9 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, pos = n) #define hlist_for_each_rcu(pos, head) \ - for ((pos) = (head)->first; pos && ({ prefetch((pos)->next); 1; }); \ - (pos) = rcu_dereference((pos)->next)) + for ((pos) = (head)->first; \ + rcu_dereference((pos)) && ({ prefetch((pos)->next); 1; }); \ + (pos) = (pos)->next) /** * hlist_for_each_entry - iterate over list of given type @@ -762,9 +767,9 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, */ #define hlist_for_each_entry_rcu(tpos, pos, head, member) \ for (pos = (head)->first; \ - pos && ({ prefetch(pos->next); 1;}) && \ + rcu_dereference(pos) && ({ prefetch(pos->next); 1;}) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ - pos = rcu_dereference(pos->next)) + pos = pos->next) #else #warning "don't include kernel headers in userspace" -- cgit v0.10.2 From 0aec4867dca149e2049e8439b76bd82ad9dac52c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 16 Oct 2005 20:29:22 -0700 Subject: [PATCH] SVGATextMode fix Fix bug 5441. I didn't know about messy programs like svgatextmode... Couldn't this be integrated in some linux/drivers/video/console/svgacon.c ?... So because of the existence of the svgatextmode program, the kernel is not supposed to touch to CRT_OVERFLOW/SYNC_END/DISP/DISP_END/OFFSET ? Disabling the check in vgacon_resize() might help indeed, but I'm really not sure whether it will work for any chipset: in my patch, CRT registers are set at each console switch, since stty rows/cols apply to consoles separately... The attached solution is to keep the test, but if it fails, we assume that the caller knows what it does (i.e. it is svgatextmode) and then disable any further call to vgacon_doresize. Svgatextmode is usually used to _expand_ the display, not to shrink it. And it is harmless in the case of a too big stty rows/cols: the display will just be cropped. I tested it on my laptop, and it works fine with svgatextmode. A better solution would be that svgatextmode explicitely tells the kernel not to care about video timing, but for this an interface needs be defined and svgatextmode be patched. Signed-off-by: Samuel Thibault Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 6ef6f77..809fee2 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -565,7 +565,11 @@ static int vgacon_switch(struct vc_data *c) scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); - vgacon_doresize(c, c->vc_cols, c->vc_rows); + if (!(vga_video_num_columns % 2) && + vga_video_num_columns <= ORIG_VIDEO_COLS && + vga_video_num_lines <= (ORIG_VIDEO_LINES * + vga_default_font_height) / c->vc_font.height) + vgacon_doresize(c, c->vc_cols, c->vc_rows); } return 0; /* Redrawing not needed */ @@ -1023,7 +1027,8 @@ static int vgacon_resize(struct vc_data *c, unsigned int width, if (width % 2 || width > ORIG_VIDEO_COLS || height > (ORIG_VIDEO_LINES * vga_default_font_height)/ c->vc_font.height) - return -EINVAL; + /* let svgatextmode tinker with video timings */ + return 0; if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ vgacon_doresize(c, width, height); -- cgit v0.10.2 From 9b3acc21d7677787ef456d17574a084a1c1193ae Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sun, 16 Oct 2005 20:29:24 -0700 Subject: [PATCH] fix vpx3220 offset issue in SECAM Fix bug #5404 in kernel bugzilla. It basically updates the vpx3220 initialization tables with some newer values that we've had in CVS for a while (and that, for some reason, never ended up in the kernel... must've gotten lost). Those fix a ~16 pixels noise at the top of the picture in at least SECAM, although (now that I think about it) PAL was probably affected, also. Signed-off-by: Ronald S. Bultje Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 4437bde..2bafca4 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -203,7 +203,7 @@ static const unsigned short init_ntsc[] = { 0x8c, 640, /* Horizontal length */ 0x8d, 640, /* Number of pixels */ 0x8f, 0xc00, /* Disable window 2 */ - 0xf0, 0x173, /* 13.5 MHz transport, Forced + 0xf0, 0x73, /* 13.5 MHz transport, Forced * mode, latch windows */ 0xf2, 0x13, /* NTSC M, composite input */ 0xe7, 0x1e1, /* Enable vertical standard @@ -212,38 +212,36 @@ static const unsigned short init_ntsc[] = { static const unsigned short init_pal[] = { 0x88, 23, /* Window 1 vertical begin */ - 0x89, 288 + 16, /* Vertical lines in (16 lines + 0x89, 288, /* Vertical lines in (16 lines * skipped by the VFE) */ - 0x8a, 288 + 16, /* Vertical lines out (16 lines + 0x8a, 288, /* Vertical lines out (16 lines * skipped by the VFE) */ 0x8b, 16, /* Horizontal begin */ 0x8c, 768, /* Horizontal length */ 0x8d, 784, /* Number of pixels * Must be >= Horizontal begin + Horizontal length */ 0x8f, 0xc00, /* Disable window 2 */ - 0xf0, 0x177, /* 13.5 MHz transport, Forced + 0xf0, 0x77, /* 13.5 MHz transport, Forced * mode, latch windows */ 0xf2, 0x3d1, /* PAL B,G,H,I, composite input */ - 0xe7, 0x261, /* PAL/SECAM set to 288 + 16 lines - * change to 0x241 for 288 lines */ + 0xe7, 0x241, /* PAL/SECAM set to 288 lines */ }; static const unsigned short init_secam[] = { - 0x88, 23 - 16, /* Window 1 vertical begin */ - 0x89, 288 + 16, /* Vertical lines in (16 lines + 0x88, 23, /* Window 1 vertical begin */ + 0x89, 288, /* Vertical lines in (16 lines * skipped by the VFE) */ - 0x8a, 288 + 16, /* Vertical lines out (16 lines + 0x8a, 288, /* Vertical lines out (16 lines * skipped by the VFE) */ 0x8b, 16, /* Horizontal begin */ 0x8c, 768, /* Horizontal length */ 0x8d, 784, /* Number of pixels * Must be >= Horizontal begin + Horizontal length */ 0x8f, 0xc00, /* Disable window 2 */ - 0xf0, 0x177, /* 13.5 MHz transport, Forced + 0xf0, 0x77, /* 13.5 MHz transport, Forced * mode, latch windows */ 0xf2, 0x3d5, /* SECAM, composite input */ - 0xe7, 0x261, /* PAL/SECAM set to 288 + 16 lines - * change to 0x241 for 288 lines */ + 0xe7, 0x241, /* PAL/SECAM set to 288 lines */ }; static const unsigned char init_common[] = { -- cgit v0.10.2 From de21eb63add932c61e018d20a760dcaed8c3e40c Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sun, 16 Oct 2005 20:29:25 -0700 Subject: [PATCH] fix black/white-only svideo input in vpx3220 decoder Fix the fact that the svideo input will only give input in black/white in some circumstances. Reason is that in the PCI controller driver (zr36067), after setting input, we reset norm, which overwrites the input register with the default. This patch makes it always set the correct value for the input when changing norm. Signed-off-by: Ronald S. Bultje Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 2bafca4..137b58f 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c @@ -408,6 +408,12 @@ vpx3220_command (struct i2c_client *client, case DECODER_SET_NORM: { int *iarg = arg, data; + int temp_input; + + /* Here we back up the input selection because it gets + overwritten when we fill the registers with the + choosen video norm */ + temp_input = vpx3220_fp_read(client, 0xf2); dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n", I2C_NAME(client), *iarg); @@ -447,6 +453,10 @@ vpx3220_command (struct i2c_client *client, } decoder->norm = *iarg; + + /* And here we set the backed up video input again */ + vpx3220_fp_write(client, 0xf2, temp_input | 0x0010); + udelay(10); } break; -- cgit v0.10.2 From 2cc78eb52bc1ae89f0a4fa5a00eb998dffde4a9f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 17 Oct 2005 09:10:15 -0700 Subject: Increase default RCU batching sharply Dipankar made RCU limit the batch size to improve latency, but that approach is unworkable: it can cause the RCU queues to grow without bounds, since the batch limiter ended up limiting the callbacks. So make the limit much higher, and start planning on instead limiting the batch size by doing RCU callbacks more often if the queue looks like it might be growing too long. Signed-off-by: Linus Torvalds diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index bef3b69..dd99415 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -71,7 +71,7 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; /* Fake initialization required by compiler */ static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; -static int maxbatch = 10; +static int maxbatch = 10000; #ifndef __HAVE_ARCH_CMPXCHG /* -- cgit v0.10.2 From e9b765decfb49ddc105d303d491e1bee9769436f Mon Sep 17 00:00:00 2001 From: Olav Kongas Date: Mon, 17 Oct 2005 14:30:43 -0700 Subject: [PATCH] isp116x-hcd: fix handling of short transfers Increased use of scatter-gather by usb-storage driver after 2.6.13 has exposed a buggy codepath in isp116x-hcd, which was probably never visited before: bug happened only for those urbs, for which URB_SHORT_NOT_OK was set AND short transfer occurred. The fix attached was tested in 2 ways: (a) it fixed failing initialization of a flash drive with an embedded hub; (b) the fix was tested with 'usbtest' against a modified g_zero driver (on top of net2280), which generated short bulk IN transfers of various lengths including multiples and non-multiples of max_packet_length. Signed-off-by: Olav Kongas Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 41bbae8..e142056 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -326,7 +326,8 @@ static void postproc_atl_queue(struct isp116x *isp116x) usb_settoggle(udev, ep->epnum, ep->nextpid == USB_PID_OUT, - PTD_GET_TOGGLE(ptd) ^ 1); + PTD_GET_TOGGLE(ptd)); + urb->actual_length += PTD_GET_COUNT(ptd); urb->status = cc_to_error[TD_DATAUNDERRUN]; spin_unlock(&urb->lock); continue; -- cgit v0.10.2 From 13b58ee51802a45d2b8853ffe0003d9fa768195c Mon Sep 17 00:00:00 2001 From: Christian Krause Date: Mon, 17 Oct 2005 14:30:48 -0700 Subject: [PATCH] USB: fix bug in handling of highspeed usb HID devices During the development of an USB device I found a bug in the handling of Highspeed HID devices in the kernel. What happened? Highspeed HID devices are correctly recognized and enumerated by the kernel. But even if usbhid kernel module is loaded, no HID reports are received by the kernel. The output of the hardware USB analyzer told me that the host doesn't even poll for interrupt IN transfers (even the "interrupt in" USB transfer are polled by the host). After some debugging in hid-core.c I've found the reason. In case of a highspeed device, the endpoint interval is re-calculated in driver/usb/input/hid-core.c: line 1669: /* handle potential highspeed HID correctly */ interval = endpoint->bInterval; if (dev->speed == USB_SPEED_HIGH) interval = 1 << (interval - 1); Basically this calculation is correct (refer to USB 2.0 spec, 9.6.6). This new calculated value of "interval" is used as input for usb_fill_int_urb: line 1685: usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, interval); Unfortunately the same calculation as above is done a second time in usb_fill_int_urb in the file include/linux/usb.h: line 933: if (dev->speed == USB_SPEED_HIGH) urb->interval = 1 << (interval - 1); else urb->interval = interval; This means, that if the endpoint descriptor (of a high speed device) specifies e.g. bInterval = 7, the urb->interval gets the value: hid-core.c: interval = 1 << (7-1) = 0x40 = 64 urb->interval = 1 << (interval -1) = 1 << (63) = integer overflow Because of this the value of urb->interval is sometimes negative and is rejected in core/urb.c: line 353: /* too small? */ if (urb->interval <= 0) return -EINVAL; The conclusion is, that the recalculaton of the interval (which is necessary for highspeed) should not be made twice, because this is simply wrong. ;-) Re-calculation in usb_fill_int_urb makes more sense, because it is the most general approach. So it would make sense to remove it from hid-core.c. Because in hid-core.c the interval variable is only used for calling usb_fill_int_urb, it is no problem to remove the highspeed re-calculation in this file. Signed-off-by: Christian Krause Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a99865c..41f92b9 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1702,10 +1702,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ continue; - /* handle potential highspeed HID correctly */ interval = endpoint->bInterval; - if (dev->speed == USB_SPEED_HIGH) - interval = 1 << (interval - 1); /* Change the polling interval of mice. */ if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) -- cgit v0.10.2 From b3c52da33ce95747b1bff86cce716d4f1397f14a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 17 Oct 2005 06:02:00 -0400 Subject: [PATCH] NFS: Fix cache consistency races If the data cache has been marked as potentially invalid by nfs_refresh_inode, we should invalidate it rather than assume that changes are due to our own activity. Also ensure that we always start with a valid cache before declaring it to be protected by a delegation. Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index d7f7eb6..4a36839 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -85,6 +85,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct struct nfs_delegation *delegation; int status = 0; + /* Ensure we first revalidate the attributes and page cache! */ + if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR))) + __nfs_revalidate_inode(NFS_SERVER(inode), inode); + delegation = nfs_alloc_delegation(); if (delegation == NULL) return -ENOMEM; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f6b9eda..6bdcfa9 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -137,7 +137,8 @@ static int nfs_revalidate_file(struct inode *inode, struct file *filp) struct nfs_inode *nfsi = NFS_I(inode); int retval = 0; - if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) + if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)) + || nfs_attribute_timeout(inode)) retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); nfs_revalidate_mapping(inode, filp->f_mapping); return 0; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6922469d..6be46d2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1226,10 +1226,6 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) loff_t cur_size, new_isize; int data_unstable; - /* Do we hold a delegation? */ - if (nfs_have_delegation(inode, FMODE_READ)) - return 0; - spin_lock(&inode->i_lock); /* Are we in the process of updating data on the server? */ @@ -1350,7 +1346,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign nfsi->read_cache_jiffies = fattr->timestamp; /* Are we racing with known updates of the metadata on the server? */ - data_unstable = ! nfs_verify_change_attribute(inode, verifier); + data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || + (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); /* Check if our cached file size is stale */ new_isize = nfs_size_to_loff_t(fattr->size); -- cgit v0.10.2 From 6ce969171d5187f7621be68c0ebbc7fb02ec53f1 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 17 Oct 2005 06:03:23 -0400 Subject: [PATCH] NFS: Fix Oopsable/unnecessary i_count manipulations in nfs_wait_on_inode() Oopsable since nfs_wait_on_inode() can get called as part of iput_final(). Unnecessary since the caller had better be damned sure that the inode won't disappear from underneath it anyway. Signed-off-by: Trond Myklebust Signed-off-by: Linus Torvalds diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6be46d2..d4eadee 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -877,12 +877,10 @@ static int nfs_wait_on_inode(struct inode *inode) sigset_t oldmask; int error; - atomic_inc(&inode->i_count); rpc_clnt_sigmask(clnt, &oldmask); error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, nfs_wait_schedule, TASK_INTERRUPTIBLE); rpc_clnt_sigunmask(clnt, &oldmask); - iput(inode); return error; } -- cgit v0.10.2 From 47d6b08334a43fafa61a587f721fa21ef65d81be Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 17 Oct 2005 18:49:42 +0400 Subject: [PATCH] posix-timers: fix task accounting Make sure we release the task struct properly when releasing pending timers. release_task() does write_lock_irq(&tasklist_lock), so it can't race with run_posix_cpu_timers() on any cpu. Signed-off-by: Oleg Nesterov Signed-off-by: Linus Torvalds diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index ad85d3f..7a51a55 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -424,6 +424,7 @@ static void cleanup_timers(struct list_head *head, cputime_t ptime = cputime_add(utime, stime); list_for_each_entry_safe(timer, next, head, entry) { + put_task_struct(timer->task); timer->task = NULL; list_del_init(&timer->entry); if (cputime_lt(timer->expires.cpu, ptime)) { @@ -436,6 +437,7 @@ static void cleanup_timers(struct list_head *head, ++head; list_for_each_entry_safe(timer, next, head, entry) { + put_task_struct(timer->task); timer->task = NULL; list_del_init(&timer->entry); if (cputime_lt(timer->expires.cpu, utime)) { @@ -448,6 +450,7 @@ static void cleanup_timers(struct list_head *head, ++head; list_for_each_entry_safe(timer, next, head, entry) { + put_task_struct(timer->task); timer->task = NULL; list_del_init(&timer->entry); if (timer->expires.sched < sched_time) { -- cgit v0.10.2 From cc675230a9ca17010694bc8bd3c69ca9adf2efef Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 17 Oct 2005 13:01:57 -0400 Subject: [PATCH] Fix and clean up quirk_intel_ide_combined() configuration This change makes quirk_intel_ide_combined() dependent on the precise conditions under which it is needed: * IDE is built in * IDE SATA option is not set * ata_piix or ahci drivers are enabled This fixes an issue where some modular configurations would not cause the quirk to be enabled. Signed-off-by: Jeff Garzik Signed-off-by: Linus torvalds diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 11ca4438..a6a630a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1233,7 +1233,7 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic ); #endif -#ifdef CONFIG_SCSI_SATA +#ifdef CONFIG_SCSI_SATA_INTEL_COMBINED static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev) { u8 prog, comb, tmp; @@ -1310,7 +1310,7 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev) request_region(0x170, 8, "libata"); /* port 1 */ } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_combined ); -#endif /* CONFIG_SCSI_SATA */ +#endif /* CONFIG_SCSI_SATA_INTEL_COMBINED */ int pcie_mch_quirk; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 20019b8..3ee9b8b 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -553,6 +553,11 @@ config SCSI_SATA_VITESSE If unsure, say N. +config SCSI_SATA_INTEL_COMBINED + bool + depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX) + default y + config SCSI_BUSLOGIC tristate "BusLogic SCSI support" depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API -- cgit v0.10.2 From 5ee832dbc6770135ec8d63296af0a4374557bb79 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 17 Oct 2005 20:01:21 +0200 Subject: [PATCH] rcu: keep rcu callback event counter This makes call_rcu() keep track of how many events there are on the RCU list, and cause a reschedule event when the list gets too long. This helps keep RCU event lists down. Signed-off-by: Linus Torvalds diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 4e65eb4..70191a5 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -94,6 +94,7 @@ struct rcu_data { long batch; /* Batch # for current RCU batch */ struct rcu_head *nxtlist; struct rcu_head **nxttail; + long count; /* # of queued items */ struct rcu_head *curlist; struct rcu_head **curtail; struct rcu_head *donelist; diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index dd99415..2559d4b 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -109,6 +109,10 @@ void fastcall call_rcu(struct rcu_head *head, rdp = &__get_cpu_var(rcu_data); *rdp->nxttail = head; rdp->nxttail = &head->next; + + if (unlikely(++rdp->count > 10000)) + set_need_resched(); + local_irq_restore(flags); } @@ -140,6 +144,12 @@ void fastcall call_rcu_bh(struct rcu_head *head, rdp = &__get_cpu_var(rcu_bh_data); *rdp->nxttail = head; rdp->nxttail = &head->next; + rdp->count++; +/* + * Should we directly call rcu_do_batch() here ? + * if (unlikely(rdp->count > 10000)) + * rcu_do_batch(rdp); + */ local_irq_restore(flags); } @@ -157,6 +167,7 @@ static void rcu_do_batch(struct rcu_data *rdp) next = rdp->donelist = list->next; list->func(list); list = next; + rdp->count--; if (++count >= maxbatch) break; } -- cgit v0.10.2 From b65574fec5db1211bce7fc8bec7a2b32486e0670 Mon Sep 17 00:00:00 2001 From: David McCullough Date: Mon, 17 Oct 2005 16:43:29 -0700 Subject: [PATCH] output of /proc/maps on nommu systems is incomplete Currently you do not get all the map entries on nommu systems because the start function doesn't index into the list using the value of "pos". Signed-off-by: David McCullough Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index f3bf016..cff10ab 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -91,6 +91,7 @@ static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos) next = _rb; break; } + pos--; } return next; -- cgit v0.10.2 From 9ac0b9c1927228a38a71216536176af8811a435a Mon Sep 17 00:00:00 2001 From: Stephan Brodkorb Date: Mon, 17 Oct 2005 16:43:30 -0700 Subject: [PATCH] n_r3964 mod_timer() fix Since Revision 1.10 was released the n_r3964 module wasn't able to receive any data. The reason for that behavior is because there were some wrong calls of mod_timer(...) in the function receive_char (...). This patch should fix this problem and was successfully tested with talking to some kuka industrial robots. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 97d6dc2..853c98c 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -695,7 +695,7 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c) { TRACE_PE("IDLE - got STX but no space in rx_queue!"); pInfo->state=R3964_WAIT_FOR_RX_BUF; - mod_timer(&pInfo->tmr, R3964_TO_NO_BUF); + mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF); break; } start_receiving: @@ -705,7 +705,7 @@ start_receiving: pInfo->last_rx = 0; pInfo->flags &= ~R3964_ERROR; pInfo->state=R3964_RECEIVING; - mod_timer(&pInfo->tmr, R3964_TO_ZVZ); + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); pInfo->nRetry = 0; put_char(pInfo, DLE); flush(pInfo); @@ -732,7 +732,7 @@ start_receiving: if(pInfo->flags & R3964_BCC) { pInfo->state = R3964_WAIT_FOR_BCC; - mod_timer(&pInfo->tmr, R3964_TO_ZVZ); + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); } else { @@ -744,7 +744,7 @@ start_receiving: pInfo->last_rx = c; char_to_buf: pInfo->rx_buf[pInfo->rx_position++] = c; - mod_timer(&pInfo->tmr, R3964_TO_ZVZ); + mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); } } /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ -- cgit v0.10.2 From 5cc9eeef9a9567acdfc2f6943f24381bf460f008 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 17 Oct 2005 16:43:31 -0700 Subject: [PATCH] Fix /proc/acpi/events around suspend Fix -EIO on /proc/acpi/events after suspends. This actually breaks suspending by power button in many setups. Signed-off-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index bfa8b76..2dbb1b0 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -58,9 +58,8 @@ acpi_system_read_event(struct file *file, char __user * buffer, size_t count, return_VALUE(-EAGAIN); result = acpi_bus_receive_event(&event); - if (result) { - return_VALUE(-EIO); - } + if (result) + return_VALUE(result); chars_remaining = sprintf(str, "%s %s %08x %08x\n", event.device_class ? event. -- cgit v0.10.2 From e7507ed91e093b9e4e218e41ebfdce05458258fc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 17 Oct 2005 16:43:32 -0700 Subject: [PATCH] uniput - fix crash on SMP Only signal completion after marking request slot as free, otherwise other processor can free request structure before we finish using it. Signed-off-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d5c5b32..4015a91 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -90,11 +90,11 @@ static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request) { - complete(&request->done); - /* Mark slot as available */ udev->requests[request->id] = NULL; wake_up_interruptible(&udev->requests_waitq); + + complete(&request->done); } static int uinput_request_submit(struct input_dev *dev, struct uinput_request *request) -- cgit v0.10.2 From 4faa5285283fad081443e3612ca426a311bb6c7e Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 17 Oct 2005 16:43:33 -0700 Subject: [PATCH] aio: revert lock_kiocb() lock_kiocb() was introduced to serialize retrying and cancellation. In the process of doing so it tried to sleep waiting for KIF_LOCKED while holding the ctx_lock spinlock. Recent fixes have ensured that multiple concurrent retries won't be attempted for a given iocb. Cancel has other problems and has no significant in-tree users that have been complaining about it. So for the immediate future we'll revert sleeping with the lock held and will address proper cancellation and retry serialization in the future. Signed-off-by: Zach Brown Acked-by: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/aio.c b/fs/aio.c index d6b1551..9fe7216 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -398,7 +398,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) if (unlikely(!req)) return NULL; - req->ki_flags = 1 << KIF_LOCKED; + req->ki_flags = 0; req->ki_users = 2; req->ki_key = 0; req->ki_ctx = ctx; @@ -547,25 +547,6 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id) return ioctx; } -static int lock_kiocb_action(void *param) -{ - schedule(); - return 0; -} - -static inline void lock_kiocb(struct kiocb *iocb) -{ - wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action, - TASK_UNINTERRUPTIBLE); -} - -static inline void unlock_kiocb(struct kiocb *iocb) -{ - kiocbClearLocked(iocb); - smp_mb__after_clear_bit(); - wake_up_bit(&iocb->ki_flags, KIF_LOCKED); -} - /* * use_mm * Makes the calling kernel thread take on the specified @@ -796,9 +777,7 @@ static int __aio_run_iocbs(struct kioctx *ctx) * Hold an extra reference while retrying i/o. */ iocb->ki_users++; /* grab extra reference */ - lock_kiocb(iocb); aio_run_iocb(iocb); - unlock_kiocb(iocb); if (__aio_put_req(ctx, iocb)) /* drop extra ref */ put_ioctx(ctx); } @@ -1542,7 +1521,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, spin_lock_irq(&ctx->ctx_lock); aio_run_iocb(req); - unlock_kiocb(req); if (!list_empty(&ctx->run_list)) { /* drain the run list */ while (__aio_run_iocbs(ctx)) @@ -1674,7 +1652,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, if (NULL != cancel) { struct io_event tmp; pr_debug("calling cancel\n"); - lock_kiocb(kiocb); memset(&tmp, 0, sizeof(tmp)); tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; tmp.data = kiocb->ki_user_data; @@ -1686,7 +1663,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, if (copy_to_user(result, &tmp, sizeof(tmp))) ret = -EFAULT; } - unlock_kiocb(kiocb); } else ret = -EINVAL; diff --git a/include/linux/aio.h b/include/linux/aio.h index 60def65..0decf66 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -24,7 +24,12 @@ struct kioctx; #define KIOCB_SYNC_KEY (~0U) /* ki_flags bits */ -#define KIF_LOCKED 0 +/* + * This may be used for cancel/retry serialization in the future, but + * for now it's unused and we probably don't want modules to even + * think they can use it. + */ +/* #define KIF_LOCKED 0 */ #define KIF_KICKED 1 #define KIF_CANCELLED 2 -- cgit v0.10.2 From 39ca371c45b04cd50d0974030ae051906fc516b6 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Mon, 17 Oct 2005 16:43:34 -0700 Subject: [PATCH] kbuild: Eliminate build error when KALLSYMS not defined The following build error happens with 2.6.14-rc4 when CONFIG_KALLSYMS is not defined. The error message in a fragment of the output was: CC arch/i386/lib/usercopy.o AR arch/i386/lib/lib.a /bin/sh: line 1: +@: command not found make[3]: warning: jobserver unavailable: using -j1. Add `+' to parent make rule. CHK include/linux/compile.h Signed-off-by: Mark Rustad Signed-off-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index 504ba3c..be33d75 100644 --- a/Makefile +++ b/Makefile @@ -660,8 +660,10 @@ quiet_cmd_sysmap = SYSMAP # Link of vmlinux # If CONFIG_KALLSYMS is set .version is already updated # Generate System.map and verify that the content is consistent - +# Use + in front of the vmlinux_version rule to silent warning with make -j2 +# First command is ':' to allow us to use + in front of the rule define rule_vmlinux__ + : $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version)) $(call cmd,vmlinux__) -- cgit v0.10.2 From c086f282c01d7e5a887c3f7b190520538267f12e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 18 Oct 2005 07:51:34 +0100 Subject: [ARM] 3018/1: S3C2410 - check de-referenced device is really a platform device Patch from Ben Dooks Check that the device we are looking at is really a platform device before trying to cast it to one to find out the platform bus number. Thanks to RMK for pointing this out. Signed-off-by: Ben Dooks Signed-off-by: Russell King diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index f596082..8b3d5dc 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -98,7 +98,10 @@ struct clk *clk_get(struct device *dev, const char *id) struct clk *clk = ERR_PTR(-ENOENT); int idno; - idno = (dev == NULL) ? -1 : to_platform_device(dev)->id; + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; down(&clocks_sem); -- cgit v0.10.2 From 9b15c6c4e22cbb381373fac3bee8cacb811147a9 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 18 Oct 2005 07:51:34 +0100 Subject: [ARM] 3019/1: fix wrong comments Patch from Nicolas Pitre Signed-off-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/include/asm-arm/locks.h b/include/asm-arm/locks.h index f08dc84..852220e 100644 --- a/include/asm-arm/locks.h +++ b/include/asm-arm/locks.h @@ -103,7 +103,7 @@ ({ \ smp_mb(); \ __asm__ __volatile__( \ - "@ up_op_read\n" \ + "@ up_op_write\n" \ "1: ldrex lr, [%0]\n" \ " adds lr, lr, %1\n" \ " strex ip, lr, [%0]\n" \ @@ -231,7 +231,7 @@ #define __up_op_write(ptr,wake) \ ({ \ __asm__ __volatile__( \ - "@ up_op_read\n" \ + "@ up_op_write\n" \ " mrs ip, cpsr\n" \ " orr lr, ip, #128\n" \ " msr cpsr_c, lr\n" \ -- cgit v0.10.2 From ad1b472bea1bbcd8dc7fd92f6952d8b2d8355edb Mon Sep 17 00:00:00 2001 From: Kenneth Tan Date: Tue, 18 Oct 2005 07:51:35 +0100 Subject: [ARM] 3020/1: Fixes typo error CONFIG_CPU_IXP465, which should be CONFIG_CPU_IXP46X Patch from Kenneth Tan The cpu_is_ixp465 macro in include/asm-arm/arch-ixp4xx/hardware.h is always returning 0 because #ifdef CONFIG_CPU_IXP465 is always false. Signed-off-by: Kenneth Tan Signed-off-by: Russell King diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h index 4ac964b..55d85ee 100644 --- a/include/asm-arm/arch-ixp4xx/hardware.h +++ b/include/asm-arm/arch-ixp4xx/hardware.h @@ -27,7 +27,7 @@ #define pcibios_assign_all_busses() 1 -#if defined(CONFIG_CPU_IXP465) && !defined(__ASSEMBLY__) +#if defined(CONFIG_CPU_IXP46X) && !defined(__ASSEMBLY__) extern unsigned int processor_id; #define cpu_is_ixp465() ((processor_id & 0xffffffc0) == 0x69054200) #else -- cgit v0.10.2 From 251b928cdff5f12e7da8f56e8933e2b58ba08456 Mon Sep 17 00:00:00 2001 From: Kenneth Tan Date: Tue, 18 Oct 2005 07:53:35 +0100 Subject: [ARM] 3021/1: Interrupt 0 bug fix for ixp4xx Patch from Kenneth Tan The get_irqnr_and_base subroutine of ixp4xx does not take interrupt 0 condition into account properly. We should not perform "subs" here. The Z flag will be set when interrupt 0 occur, which resulting "movne r1, sp" in the caller routine (irq_handler) not being executed. When interrupt 0 occur: o if CONFIG_CPU_IXP46X is not set, "subs" will set the Z flag and return o if CONFIG_CPU_IXP46X is set, codes in upper interrupt handling will be trigerred. But since this is not supper interrupt, the "cmp" in the upper interrupt handling portion will set the Z flag and return Signed-off-by: Kenneth Tan Signed-off-by: Russell King diff --git a/include/asm-arm/arch-ixp4xx/entry-macro.S b/include/asm-arm/arch-ixp4xx/entry-macro.S index 455da64..323b0bc 100644 --- a/include/asm-arm/arch-ixp4xx/entry-macro.S +++ b/include/asm-arm/arch-ixp4xx/entry-macro.S @@ -15,25 +15,26 @@ ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET) ldr \irqstat, [\irqstat] @ get interrupts cmp \irqstat, #0 - beq 1001f + beq 1001f @ upper IRQ? clz \irqnr, \irqstat mov \base, #31 - subs \irqnr, \base, \irqnr + sub \irqnr, \base, \irqnr + b 1002f @ lower IRQ being + @ handled 1001: /* * IXP465 has an upper IRQ status register */ #if defined(CONFIG_CPU_IXP46X) - bne 1002f ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET) ldr \irqstat, [\irqstat] @ get upper interrupts mov \irqnr, #63 clz \irqstat, \irqstat cmp \irqstat, #32 subne \irqnr, \irqnr, \irqstat -1002: #endif +1002: .endm -- cgit v0.10.2 From 1e65174a3378494608e8ed7f8c74d658be9a0fb2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 18 Oct 2005 08:26:15 -0700 Subject: Add some basic .gitignore files This still leaves driver and architecture-specific subdirectories alone, but gets rid of the bulk of the "generic" generated files that we should ignore. Signed-off-by: Linus Torvalds diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5014bfa --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# Normal rules +# +.* +*.o +*.a +*.s +*.ko +*.mod.c + +# +# Top-level generic files +# +vmlinux* +System.map +Module.symvers + +# +# Generated include files +# +include/asm +include/config +include/linux/autoconf.h +include/linux/compile.h +include/linux/version.h + diff --git a/drivers/char/.gitignore b/drivers/char/.gitignore new file mode 100644 index 0000000..2b6b1d7 --- /dev/null +++ b/drivers/char/.gitignore @@ -0,0 +1,3 @@ +consolemap_deftbl.c +defkeymap.c + diff --git a/drivers/pci/.gitignore b/drivers/pci/.gitignore new file mode 100644 index 0000000..f297ca8 --- /dev/null +++ b/drivers/pci/.gitignore @@ -0,0 +1,4 @@ +classlist.h +devlist.h +gen-devlist + diff --git a/drivers/video/logo/.gitignore b/drivers/video/logo/.gitignore new file mode 100644 index 0000000..e48355f --- /dev/null +++ b/drivers/video/logo/.gitignore @@ -0,0 +1,7 @@ +# +# Generated files +# +*_mono.c +*_vga16.c +*_clut224.c +*_gray256.c diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..3bef1ea --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,6 @@ +# +# Generated files +# +gen_crc32table +crc32table.h + diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 0000000..b46d68b --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1,4 @@ +conmakehash +kallsyms +pnmtologo + diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore new file mode 100644 index 0000000..7304e19 --- /dev/null +++ b/scripts/basic/.gitignore @@ -0,0 +1,3 @@ +fixdep +split-include +docproc diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore new file mode 100644 index 0000000..2dac344 --- /dev/null +++ b/scripts/kconfig/.gitignore @@ -0,0 +1,16 @@ +# +# Generated files +# +config* +lex.*.c +*.tab.c +*.tab.h + +# +# configuration programs +# +conf +mconf +qconf +gconf +kxgettext diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore new file mode 100644 index 0000000..e9b7abe --- /dev/null +++ b/scripts/mod/.gitignore @@ -0,0 +1,4 @@ +elfconfig.h +mk_elfconfig +modpost + diff --git a/usr/.gitignore b/usr/.gitignore new file mode 100644 index 0000000..be186a8 --- /dev/null +++ b/usr/.gitignore @@ -0,0 +1,7 @@ +# +# Generated files +# +gen_init_cpio +initramfs_data.cpio +initramfs_data.cpio.gz +initramfs_list -- cgit v0.10.2 From bb7e257ef8d8ba43cab356aa1cc1b20d0106d45f Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 18 Oct 2005 15:59:52 +0800 Subject: [PATCH] vesafb: Fix display corruption on display blank Reported by: Bob Tracy "...I've got a Toshiba notebook (730XCDT -- Pentium 150MMX) for which I'm using the Vesa FB driver. When the machine has been idle for some time and the driver attempts to powerdown the display, rather than the display going blank, it goes gray with several strange lines. When I hit the "shift" key or other-wise wake up the display, the old video state is not fully restored..." vesafb recently added a blank method which has only 2 states, powerup and powerdown. The powerdown state is used for all blanking levels, but in his case, powerdown does not work correctly for higher levels of display powersaving. Thus, for intermediate power levels, use software blanking, and use only hardware blanking for an explicit powerdown. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 1ca80264..b1243da 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -96,14 +96,14 @@ static int vesafb_blank(int blank, struct fb_info *info) int loop = 10000; u8 seq = 0, crtc17 = 0; - err = 0; - - if (blank) { + if (blank == FB_BLANK_POWERDOWN) { seq = 0x20; crtc17 = 0x00; + err = 0; } else { seq = 0x00; crtc17 = 0x80; + err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL; } vga_wseq(NULL, 0x00, 0x01); -- cgit v0.10.2 From d1972efaf24e56c06b43c40c364f9377763c2e13 Mon Sep 17 00:00:00 2001 From: Paul Schulz Date: Tue, 18 Oct 2005 19:40:32 +0100 Subject: [ARM] 3023/1: pxa-regs: Typo in ARM pxa register definitions. Patch from Paul Schulz The following trivial patch is to fix what looks like a typo in the PXA register definitions. The correction comes directly from the definition in the Intel Documentation. http://www.intel.com/design/pca/applicationsprocessors/manuals/278693.htm Intel(R) PXA 255 Processor - Developers Manual - Jan 2004 - Page 12-33 Neither 'UDCCS_IO_ROF' or 'UDCCS_IO_DME' are currently used elseware in the main code (from grep of tree)... The current definitions have been in the code since at lease 2.4.7. Signed-off-by: Paul Schulz Signed-off-by: Russell King diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 13fa2de..3af7165 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -653,7 +653,7 @@ #define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ #define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ -#define UDCCS_IO_ROF (1 << 3) /* Receive overflow */ +#define UDCCS_IO_ROF (1 << 2) /* Receive overflow */ #define UDCCS_IO_DME (1 << 3) /* DMA enable */ #define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ #define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ -- cgit v0.10.2 From 3359b54c8c07338f3a863d1109b42eebccdcf379 Mon Sep 17 00:00:00 2001 From: "Seth, Rohit" Date: Tue, 18 Oct 2005 14:15:12 -0700 Subject: [PATCH] Handle spurious page fault for hugetlb region The hugetlb pages are currently pre-faulted. At the time of mmap of hugepages, we populate the new PTEs. It is possible that HW has already cached some of the unused PTEs internally. These stale entries never get a chance to be purged in existing control flow. This patch extends the check in page fault code for hugepages. Check if a faulted address falls with in size for the hugetlb file backing it. We return VM_FAULT_MINOR for these cases (assuming that the arch specific page-faulting code purges the stale entry for the archs that need it). Signed-off-by: Rohit Seth [ This is apparently arguably an ia64 port bug. But the code won't hurt, and for now it fixes a real problem on some ia64 machines ] Signed-off-by: Linus Torvalds diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index e670b0d..42cb7d70 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -155,11 +155,24 @@ static inline void set_file_hugepages(struct file *file) { file->f_op = &hugetlbfs_file_operations; } + +static inline int valid_hugetlb_file_off(struct vm_area_struct *vma, + unsigned long address) +{ + struct inode *inode = vma->vm_file->f_dentry->d_inode; + loff_t file_off = address - vma->vm_start; + + file_off += (vma->vm_pgoff << PAGE_SHIFT); + + return (file_off < inode->i_size); +} + #else /* !CONFIG_HUGETLBFS */ #define is_file_hugepages(file) 0 #define set_file_hugepages(file) BUG() #define hugetlb_zero_setup(size) ERR_PTR(-ENOSYS) +#define valid_hugetlb_file_off(vma, address) 0 #endif /* !CONFIG_HUGETLBFS */ diff --git a/mm/memory.c b/mm/memory.c index ae8161f..8c88b97 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2045,8 +2045,18 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, inc_page_state(pgfault); - if (is_vm_hugetlb_page(vma)) - return VM_FAULT_SIGBUS; /* mapping truncation does this. */ + if (unlikely(is_vm_hugetlb_page(vma))) { + if (valid_hugetlb_file_off(vma, address)) + /* We get here only if there was a stale(zero) TLB entry + * (because of HW prefetching). + * Low-level arch code (if needed) should have already + * purged the stale entry as part of this fault handling. + * Here we just return. + */ + return VM_FAULT_MINOR; + else + return VM_FAULT_SIGBUS; /* mapping truncation does this. */ + } /* * We need the page table lock to synchronize with kswapd -- cgit v0.10.2 From 67c5587ad4047041e4fb137628076388ede05281 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 19 Oct 2005 23:00:56 +0100 Subject: [ARM] 3024/1: Add cpu_v6_proc_fin Patch from Tony Lindgren Machine restart calls cpu_proc_fin() to clean and disable cache, and turn off interrupts. This patch adds proper cpu_v6_proc_fin. Signed-off-by: Tony Lindgren Signed-off-by: Russell King diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index caf3b19..9bb5fff 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -55,7 +55,14 @@ ENTRY(cpu_v6_proc_init) mov pc, lr ENTRY(cpu_v6_proc_fin) - mov pc, lr + stmfd sp!, {lr} + cpsid if @ disable interrupts + bl v6_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x0006 @ .............ca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} /* * cpu_v6_reset(loc) -- cgit v0.10.2 From e03d13e985d48ac4885382c9e3b1510c78bd047f Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 19 Oct 2005 22:21:23 -0700 Subject: [PATCH] Fix cpu timers exit deadlock and races Oleg Nesterov reported an SMP deadlock. If there is a running timer tracking a different process's CPU time clock when the process owning the timer exits, we deadlock on tasklist_lock in posix_cpu_timer_del via exit_itimers. That code was using tasklist_lock to check for a race with __exit_signal being called on the timer-target task and clearing its ->signal. However, there is actually no such race. __exit_signal will have called posix_cpu_timers_exit and posix_cpu_timers_exit_group before it does that. Those will clear those k_itimer's association with the dying task, so posix_cpu_timer_del will return early and never reach the code in question. In addition, posix_cpu_timer_del called from exit_itimers during execve or directly from timer_delete in the process owning the timer can race with an exiting timer-target task to cause a double put on timer-target task struct. Make sure we always access cpu_timers lists with sighand lock held. Signed-off-by: Roland McGrath Signed-off-by: Chris Wright Signed-off-by: Linus Torvalds diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 7a51a55..b3f3edc 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -387,25 +387,19 @@ int posix_cpu_timer_del(struct k_itimer *timer) if (unlikely(p == NULL)) return 0; + spin_lock(&p->sighand->siglock); if (!list_empty(&timer->it.cpu.entry)) { - read_lock(&tasklist_lock); - if (unlikely(p->signal == NULL)) { - /* - * We raced with the reaping of the task. - * The deletion should have cleared us off the list. - */ - BUG_ON(!list_empty(&timer->it.cpu.entry)); - } else { - /* - * Take us off the task's timer list. - */ - spin_lock(&p->sighand->siglock); - list_del(&timer->it.cpu.entry); - spin_unlock(&p->sighand->siglock); - } - read_unlock(&tasklist_lock); + /* + * Take us off the task's timer list. We don't need to + * take tasklist_lock and check for the task being reaped. + * If it was reaped, it already called posix_cpu_timers_exit + * and posix_cpu_timers_exit_group to clear all the timers + * that pointed to it. + */ + list_del(&timer->it.cpu.entry); + put_task_struct(p); } - put_task_struct(p); + spin_unlock(&p->sighand->siglock); return 0; } -- cgit v0.10.2 From 1c59827d1da9bcd6970800d4f8a031b5859e8b4c Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 19 Oct 2005 21:23:43 -0700 Subject: [PATCH] mm: hugetlb truncation fixes hugetlbfs allows truncation of its files (should it?), but hugetlb.c often forgets that: crashes and misaccounting ensue. copy_hugetlb_page_range better grab the src page_table_lock since we don't want to guess what happens if concurrently truncated. unmap_hugepage_range rss accounting must not assume the full range was mapped. follow_hugetlb_page must guard with page_table_lock and be prepared to exit early. Restyle copy_hugetlb_page_range with a for loop like the others there. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 901ac52..a1b30d4 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -274,21 +274,22 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, { pte_t *src_pte, *dst_pte, entry; struct page *ptepage; - unsigned long addr = vma->vm_start; - unsigned long end = vma->vm_end; + unsigned long addr; - while (addr < end) { + for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { dst_pte = huge_pte_alloc(dst, addr); if (!dst_pte) goto nomem; + spin_lock(&src->page_table_lock); src_pte = huge_pte_offset(src, addr); - BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */ - entry = *src_pte; - ptepage = pte_page(entry); - get_page(ptepage); - add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE); - set_huge_pte_at(dst, addr, dst_pte, entry); - addr += HPAGE_SIZE; + if (src_pte && !pte_none(*src_pte)) { + entry = *src_pte; + ptepage = pte_page(entry); + get_page(ptepage); + add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE); + set_huge_pte_at(dst, addr, dst_pte, entry); + } + spin_unlock(&src->page_table_lock); } return 0; @@ -323,8 +324,8 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, page = pte_page(pte); put_page(page); + add_mm_counter(mm, rss, - (HPAGE_SIZE / PAGE_SIZE)); } - add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT)); flush_tlb_range(vma, start, end); } @@ -403,6 +404,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, BUG_ON(!is_vm_hugetlb_page(vma)); vpfn = vaddr/PAGE_SIZE; + spin_lock(&mm->page_table_lock); while (vaddr < vma->vm_end && remainder) { if (pages) { @@ -415,8 +417,13 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, * indexing below to work. */ pte = huge_pte_offset(mm, vaddr & HPAGE_MASK); - /* hugetlb should be locked, and hence, prefaulted */ - WARN_ON(!pte || pte_none(*pte)); + /* the hugetlb file might have been truncated */ + if (!pte || pte_none(*pte)) { + remainder = 0; + if (!i) + i = -EFAULT; + break; + } page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; @@ -434,7 +441,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, --remainder; ++i; } - + spin_unlock(&mm->page_table_lock); *length = remainder; *position = vaddr; -- cgit v0.10.2 From c367c21c93ccdaf7e1e124891633d89f9ae77f54 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 19 Oct 2005 21:23:44 -0700 Subject: [PATCH] orinoco: limit message rate Brice Goglin reports a printk storm from this driver. Fix. Acked-by: David Gibson Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index cf3daaa..15ceaf6 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -578,8 +578,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) txfid, NULL); if (err) { netif_start_queue(dev); - printk(KERN_ERR "%s: Error %d transmitting packet\n", - dev->name, err); + if (net_ratelimit()) + printk(KERN_ERR "%s: Error %d transmitting packet\n", + dev->name, err); stats->tx_errors++; goto fail; } -- cgit v0.10.2 From 4a9949d7ac9e2bc51939f27b184be6e1bd99004e Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 19 Oct 2005 21:23:46 -0700 Subject: [PATCH] raw1394: fix locking in the presence of SMP and interrupts Changes all spinlocks that can be held during an irq handler to disable interrupts while the lock is held. Changes spin_[un]lock_irq to use the irqsave/irqrestore variants for robustness and readability. In raw1394.c:handle_iso_listen(), don't grab host_info_lock at all -- we're not accessing host_info_list or host_count, and holding this lock while trying to tasklet_kill the iso tasklet this can cause an ABBA deadlock if ohci:dma_rcv_tasklet is running and tries to grab host_info_lock in raw1394.c:receive_iso. Test program attached reliably deadlocks all SMP machines I have been able to test without this patch. Signed-off-by: Andy Wingo Acked-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 6a6acbd..4cf9b8f 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -2283,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, { struct ohci1394_iso_tasklet *t; unsigned long mask; + unsigned long flags; - spin_lock(&ohci->iso_tasklet_list_lock); + spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); list_for_each_entry(t, &ohci->iso_tasklet_list, link) { mask = 1 << t->context; @@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, tasklet_schedule(&t->tasklet); } - spin_unlock(&ohci->iso_tasklet_list_lock); - + spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); } static irqreturn_t ohci_irq_handler(int irq, void *dev_id, diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 315f5ca..0470f77 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -412,6 +412,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, static ssize_t raw1394_read(struct file *file, char __user * buffer, size_t count, loff_t * offset_is_ignored) { + unsigned long flags; struct file_info *fi = (struct file_info *)file->private_data; struct list_head *lh; struct pending_request *req; @@ -435,10 +436,10 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, } } - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); lh = fi->req_complete.next; list_del(lh); - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); req = list_entry(lh, struct pending_request, list); @@ -486,6 +487,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req) static int state_initialized(struct file_info *fi, struct pending_request *req) { + unsigned long flags; struct host_info *hi; struct raw1394_khost_list *khl; @@ -499,7 +501,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) switch (req->req.type) { case RAW1394_REQ_LIST_CARDS: - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, SLAB_ATOMIC); @@ -513,7 +515,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) khl++; } } - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); if (khl != NULL) { req->req.error = RAW1394_ERROR_NONE; @@ -528,7 +530,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) break; case RAW1394_REQ_SET_CARD: - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); if (req->req.misc < host_count) { list_for_each_entry(hi, &host_info_list, list) { if (!req->req.misc--) @@ -550,7 +552,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) } else { req->req.error = RAW1394_ERROR_INVALID_ARG; } - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); req->req.length = 0; break; @@ -569,7 +571,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) { int channel = req->req.misc; - spin_lock_irq(&host_info_lock); if ((channel > 63) || (channel < -64)) { req->req.error = RAW1394_ERROR_INVALID_ARG; } else if (channel >= 0) { @@ -601,7 +602,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) req->req.length = 0; queue_complete_req(req); - spin_unlock_irq(&host_info_lock); } static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) @@ -627,6 +627,7 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) static int handle_async_request(struct file_info *fi, struct pending_request *req, int node) { + unsigned long flags; struct hpsb_packet *packet = NULL; u64 addr = req->req.address & 0xffffffffffffULL; @@ -761,9 +762,9 @@ static int handle_async_request(struct file_info *fi, hpsb_set_packet_complete_task(packet, (void (*)(void *))queue_complete_cb, req); - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); packet->generation = req->req.generation; @@ -779,6 +780,7 @@ static int handle_async_request(struct file_info *fi, static int handle_iso_send(struct file_info *fi, struct pending_request *req, int channel) { + unsigned long flags; struct hpsb_packet *packet; packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, @@ -804,9 +806,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req, (void (*)(void *))queue_complete_req, req); - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); /* Update the generation of the packet just before sending. */ packet->generation = req->req.generation; @@ -821,6 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req, static int handle_async_send(struct file_info *fi, struct pending_request *req) { + unsigned long flags; struct hpsb_packet *packet; int header_length = req->req.misc & 0xffff; int expect_response = req->req.misc >> 16; @@ -867,9 +870,9 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) hpsb_set_packet_complete_task(packet, (void (*)(void *))queue_complete_cb, req); - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); /* Update the generation of the packet just before sending. */ packet->generation = req->req.generation; @@ -885,6 +888,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, u64 addr, size_t length, u16 flags) { + unsigned long irqflags; struct pending_request *req; struct host_info *hi; struct file_info *fi = NULL; @@ -899,7 +903,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, "addr: %4.4x %8.8x length: %Zu", nodeid, (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), length); - spin_lock(&host_info_lock); + spin_lock_irqsave(&host_info_lock, irqflags); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { @@ -924,7 +928,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, if (!found) { printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_ADDRESS_ERROR); } else { DBGMSG("arm_read addr_entry FOUND"); @@ -954,7 +958,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ } @@ -974,7 +978,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, if (!(req->data)) { free_pending_request(req); DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ } @@ -1031,13 +1035,14 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, sizeof(struct arm_request)); queue_complete_req(req); } - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (rcode); } static int arm_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t * data, u64 addr, size_t length, u16 flags) { + unsigned long irqflags; struct pending_request *req; struct host_info *hi; struct file_info *fi = NULL; @@ -1052,7 +1057,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, "addr: %4.4x %8.8x length: %Zu", nodeid, (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), length); - spin_lock(&host_info_lock); + spin_lock_irqsave(&host_info_lock, irqflags); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { @@ -1077,7 +1082,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, if (!found) { printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_ADDRESS_ERROR); } else { DBGMSG("arm_write addr_entry FOUND"); @@ -1106,7 +1111,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request my be retried */ } @@ -1118,7 +1123,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, if (!(req->data)) { free_pending_request(req); DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ } @@ -1165,7 +1170,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, sizeof(struct arm_request)); queue_complete_req(req); } - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (rcode); } @@ -1173,6 +1178,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) { + unsigned long irqflags; struct pending_request *req; struct host_info *hi; struct file_info *fi = NULL; @@ -1198,7 +1204,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, be32_to_cpu(data), be32_to_cpu(arg)); } - spin_lock(&host_info_lock); + spin_lock_irqsave(&host_info_lock, irqflags); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { @@ -1224,7 +1230,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, if (!found) { printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_ADDRESS_ERROR); } else { DBGMSG("arm_lock addr_entry FOUND"); @@ -1307,7 +1313,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ } @@ -1316,7 +1322,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, if (!(req->data)) { free_pending_request(req); DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ } @@ -1382,7 +1388,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, sizeof(struct arm_response) + 2 * sizeof(*store)); queue_complete_req(req); } - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (rcode); } @@ -1390,6 +1396,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) { + unsigned long irqflags; struct pending_request *req; struct host_info *hi; struct file_info *fi = NULL; @@ -1422,7 +1429,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); } - spin_lock(&host_info_lock); + spin_lock_irqsave(&host_info_lock, irqflags); hi = find_host_info(host); /* search addressentry in file_info's for host */ if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { @@ -1449,7 +1456,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found" " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (RCODE_ADDRESS_ERROR); } else { DBGMSG("arm_lock64 addr_entry FOUND"); @@ -1533,7 +1540,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, DBGMSG("arm_lock64 -> entering notification-section"); req = __alloc_pending_request(SLAB_ATOMIC); if (!req) { - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); DBGMSG("arm_lock64 -> rcode_conflict_error"); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ @@ -1542,7 +1549,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, req->data = kmalloc(size, SLAB_ATOMIC); if (!(req->data)) { free_pending_request(req); - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); DBGMSG("arm_lock64 -> rcode_conflict_error"); return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. The request may be retried */ @@ -1609,7 +1616,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, sizeof(struct arm_response) + 2 * sizeof(*store)); queue_complete_req(req); } - spin_unlock(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, irqflags); return (rcode); } @@ -1980,6 +1987,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) struct hpsb_packet *packet = NULL; int retval = 0; quadlet_t data; + unsigned long flags; data = be32_to_cpu((u32) req->req.sendb); DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); @@ -1990,9 +1998,9 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) req->packet = packet; hpsb_set_packet_complete_task(packet, (void (*)(void *))queue_complete_cb, req); - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); packet->generation = req->req.generation; retval = hpsb_send_packet(packet); DBGMSG("write_phypacket send_packet called => retval: %d ", retval); @@ -2659,14 +2667,15 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt) { struct file_info *fi = file->private_data; unsigned int mask = POLLOUT | POLLWRNORM; + unsigned long flags; poll_wait(file, &fi->poll_wait_complete, pt); - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); if (!list_empty(&fi->req_complete)) { mask |= POLLIN | POLLRDNORM; } - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); return mask; } @@ -2710,6 +2719,7 @@ static int raw1394_release(struct inode *inode, struct file *file) struct arm_addr *arm_addr = NULL; int another_host; int csr_mod = 0; + unsigned long flags; if (fi->iso_state != RAW1394_ISO_INACTIVE) raw1394_iso_shutdown(fi); @@ -2720,13 +2730,11 @@ static int raw1394_release(struct inode *inode, struct file *file) } } - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); fi->listen_channels = 0; - spin_unlock_irq(&host_info_lock); fail = 0; /* set address-entries invalid */ - spin_lock_irq(&host_info_lock); while (!list_empty(&fi->addr_list)) { another_host = 0; @@ -2777,14 +2785,14 @@ static int raw1394_release(struct inode *inode, struct file *file) vfree(addr->addr_space_buffer); kfree(addr); } /* while */ - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); if (fail > 0) { printk(KERN_ERR "raw1394: during addr_list-release " "error(s) occurred \n"); } while (!done) { - spin_lock_irq(&fi->reqlists_lock); + spin_lock_irqsave(&fi->reqlists_lock, flags); while (!list_empty(&fi->req_complete)) { lh = fi->req_complete.next; @@ -2798,7 +2806,7 @@ static int raw1394_release(struct inode *inode, struct file *file) if (list_empty(&fi->req_pending)) done = 1; - spin_unlock_irq(&fi->reqlists_lock); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); if (!done) down_interruptible(&fi->complete_sem); @@ -2828,9 +2836,9 @@ static int raw1394_release(struct inode *inode, struct file *file) fi->host->id); if (fi->state == connected) { - spin_lock_irq(&host_info_lock); + spin_lock_irqsave(&host_info_lock, flags); list_del(&fi->list); - spin_unlock_irq(&host_info_lock); + spin_unlock_irqrestore(&host_info_lock, flags); put_device(&fi->host->device); } -- cgit v0.10.2 From 6985c43f39b3d799999c390099c56ebbee27d4f4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 19 Oct 2005 21:23:47 -0700 Subject: [PATCH] Three one-liners in md.c The main problem fixes is that in certain situations stopping md arrays may take longer than you expect, or may require multiple attempts. This would only happen when resync/recovery is happening. This patch fixes three vaguely related bugs. 1/ The recent change to use kthreads got the setting of the process name wrong. This fixes it. 2/ The recent change to use kthreads lost the ability for md threads to be signalled with SIG_KILL. This restores that. 3/ There is a long standing bug in that if: - An array needs recovery (onto a hot-spare) and - The recovery is being blocked because some other array being recovered shares a physical device and - The recovery thread is killed with SIG_KILL Then the recovery will appear to have completed with no IO being done, which can cause data corruption. This patch makes sure that incomplete recovery will be treated as incomplete. Note that any kernel affected by bug 2 will not suffer the problem of bug 3, as the signal can never be delivered. Thus the current 2.6.14-rc kernels are not susceptible to data corruption. Note also that if arrays are shutdown (with "mdadm -S" or "raidstop") then the problem doesn't occur. It only happens if a SIGKILL is independently delivered as done by 'init' when shutting down. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/md/md.c b/drivers/md/md.c index 2897df9..e947607 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3063,6 +3063,7 @@ static int md_thread(void * arg) * many dirty RAID5 blocks. */ + allow_signal(SIGKILL); complete(thread->event); while (!kthread_should_stop()) { void (*run)(mddev_t *); @@ -3111,7 +3112,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, thread->mddev = mddev; thread->name = name; thread->timeout = MAX_SCHEDULE_TIMEOUT; - thread->tsk = kthread_run(md_thread, thread, mdname(thread->mddev)); + thread->tsk = kthread_run(md_thread, thread, name, mdname(thread->mddev)); if (IS_ERR(thread->tsk)) { kfree(thread); return NULL; @@ -3569,6 +3570,7 @@ static void md_do_sync(mddev_t *mddev) try_again: if (signal_pending(current)) { flush_signals(current); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto skip; } ITERATE_MDDEV(mddev2,tmp) { -- cgit v0.10.2 From 83bcbf8dad86c217ef70b4b4d53811422bb79dfa Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 19 Oct 2005 21:23:49 -0700 Subject: [PATCH] ppc64: Fix error in vDSO 32 bits date The implementation of __kernel_gettimeofday() in the 32 bits vDSO has a small bug (a typo actually) that will cause it to lose 1 bit of precision. Not terribly bad but worth fixing. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S index 07f1c1c..e243c1d 100644 --- a/arch/ppc64/kernel/vdso32/gettimeofday.S +++ b/arch/ppc64/kernel/vdso32/gettimeofday.S @@ -109,7 +109,7 @@ __do_get_xsec: lwz r6,(CFG_TB_TO_XS+4)(r9) mulhwu r4,r7,r5 mulhwu r6,r7,r6 - mullw r6,r7,r5 + mullw r0,r7,r5 addc r6,r6,r0 /* At this point, we have the scaled xsec value in r4 + XER:CA -- cgit v0.10.2 From f9b25fabfddf142b5af8268692701d386cf37e4f Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 19 Oct 2005 21:23:49 -0700 Subject: [PATCH] Export RCS_TAR_IGNORE for rpm targets The variable RCS_TAR_IGNORE is used in scripts/packaging/Makefile, but not exported from the main Makefile, so it's never used. This results in the rpm targets being very unhappy in quilted trees. Signed-off-by: Tom Rini Acked-by: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Makefile b/Makefile index be33d75..91de6be 100644 --- a/Makefile +++ b/Makefile @@ -372,7 +372,7 @@ export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_ve # Files to ignore in find ... statements RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o -RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg +export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg # =========================================================================== # Rules shared between *config targets and build targets -- cgit v0.10.2 From d1209d049bbc3df66650f8417637be4f7b57b604 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 19 Oct 2005 21:23:51 -0700 Subject: [PATCH] Threads shouldn't inherit PF_NOFREEZE The PF_NOFREEZE process flag should not be inherited when a thread is forked. This patch (as585) removes the flag from the child. This problem is starting to show up more and more as drivers turn to the kthread API instead of using kernel_thread(). As a result, their kernel threads are now children of the kthread worker instead of modprobe, and they inherit the PF_NOFREEZE flag. This can cause problems during system suspend; the kernel threads are not getting frozen as they ought to be. Signed-off-by: Alan Stern Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/fork.c b/kernel/fork.c index 533ce27..280bd44 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -848,7 +848,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) { unsigned long new_flags = p->flags; - new_flags &= ~PF_SUPERPRIV; + new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE); new_flags |= PF_FORKNOEXEC; if (!(clone_flags & CLONE_PTRACE)) p->ptrace = 0; -- cgit v0.10.2 From 11909d64389c24b409e20f0eeafdc262e0a55788 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 19 Oct 2005 21:23:51 -0700 Subject: [PATCH] fix MGA DRM regression before 2.6.14 I've gotten a report on lkml, of a possible regression in the MGA DRM in 2.6.14-rc4 (since -rc1), I haven't been able to reproduce it here, but I've figured out some possible issues in the mga code that were definitely wrong, some of these are from DRM CVS, the main fix is the agp enable bit on the old code path still used by everyone..... Signed-off-by: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index fc7d4a5..c8e1b6c 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -437,7 +437,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, drm_mga_dma_bootstrap_t * dma_bs) { drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; - const unsigned int warp_size = mga_warp_microcode_size(dev_priv); + unsigned int warp_size = mga_warp_microcode_size(dev_priv); int err; unsigned offset; const unsigned secondary_size = dma_bs->secondary_bin_count @@ -499,6 +499,12 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, return err; } + /* Make drm_addbufs happy by not trying to create a mapping for less + * than a page. + */ + if (warp_size < PAGE_SIZE) + warp_size = PAGE_SIZE; + offset = 0; err = drm_addmap( dev, offset, warp_size, _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp ); @@ -587,7 +593,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev, drm_mga_dma_bootstrap_t * dma_bs) { drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private; - const unsigned int warp_size = mga_warp_microcode_size(dev_priv); + unsigned int warp_size = mga_warp_microcode_size(dev_priv); unsigned int primary_size; unsigned int bin_count; int err; @@ -599,6 +605,12 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev, return DRM_ERR(EFAULT); } + /* Make drm_addbufs happy by not trying to create a mapping for less + * than a page. + */ + if (warp_size < PAGE_SIZE) + warp_size = PAGE_SIZE; + /* The proper alignment is 0x100 for this mapping */ err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, _DRM_READ_ONLY, &dev_priv->warp); @@ -812,6 +824,10 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) } if (! dev_priv->used_new_dma_init) { + + dev_priv->dma_access = MGA_PAGPXFER; + dev_priv->wagp_enable = MGA_WAGP_ENABLE; + dev_priv->status = drm_core_findmap(dev, init->status_offset); if (!dev_priv->status) { DRM_ERROR("failed to find status page!\n"); @@ -928,7 +944,7 @@ static int mga_do_cleanup_dma( drm_device_t *dev ) drm_mga_private_t *dev_priv = dev->dev_private; if ((dev_priv->warp != NULL) - && (dev_priv->mmio->type != _DRM_CONSISTENT)) + && (dev_priv->warp->type != _DRM_CONSISTENT)) drm_core_ioremapfree(dev_priv->warp, dev); if ((dev_priv->primary != NULL) -- cgit v0.10.2 From 51b190b304bbeb1090ba20b0623d39917fa62997 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Wed, 19 Oct 2005 22:45:14 -0700 Subject: [PATCH] `unaligned access' in acpi get_root_bridge_busnr() In drivers/acpi/glue.c the address of an integer is cast to the address of an unsigned long. This breaks on systems where a long is larger than an int --- for a start the int can be misaligned; for a second the assignment through the pointer will overwrite part of the next variable. Signed-off-by: Peter Chubb Acked-by: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index e36c5da..3937adf 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -96,7 +96,7 @@ struct acpi_find_pci_root { static acpi_status do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) { - int *busnr = (int *)data; + unsigned long *busnr = (unsigned long *)data; struct acpi_resource_address64 address; if (resource->id != ACPI_RSTYPE_ADDRESS16 && @@ -115,13 +115,13 @@ do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) static int get_root_bridge_busnr(acpi_handle handle) { acpi_status status; - int bus, bbn; + unsigned long bus, bbn; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, - (unsigned long *)&bbn); + &bbn); if (status == AE_NOT_FOUND) { /* Assume bus = 0 */ printk(KERN_INFO PREFIX @@ -153,7 +153,7 @@ static int get_root_bridge_busnr(acpi_handle handle) } exit: acpi_os_free(buffer.pointer); - return bbn; + return (int)bbn; } static acpi_status -- cgit v0.10.2 From 281dd25cdc0d6903929b79183816d151ea626341 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Wed, 19 Oct 2005 15:52:18 -0700 Subject: [PATCH] swiotlb: make sure initial DMA allocations really are in DMA memory This introduces a limit parameter to the core bootmem allocator; The new parameter indicates that physical memory allocated by the bootmem allocator should be within the requested limit. We also introduce alloc_bootmem_low_pages_limit, alloc_bootmem_node_limit, alloc_bootmem_low_pages_node_limit apis, but alloc_bootmem_low_pages_limit is the only api used for swiotlb. The existing alloc_bootmem_low_pages() api could instead have been changed and made to pass right limit to the core allocator. But that would make the patch more intrusive for 2.6.14, as other arches use alloc_bootmem_low_pages(). We may be done that post 2.6.14 as a cleanup. With this, swiotlb gets memory within 4G for both x86_64 and ia64 arches. Signed-off-by: Yasunori Goto Cc: Ravikiran G Thirumalai Signed-off-by: Linus Torvalds diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c index dbc0b3e..a604efc 100644 --- a/arch/ia64/lib/swiotlb.c +++ b/arch/ia64/lib/swiotlb.c @@ -123,8 +123,8 @@ swiotlb_init_with_default_size (size_t default_size) /* * Get IO TLB memory from the low pages */ - io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * - (1 << IO_TLB_SHIFT)); + io_tlb_start = alloc_bootmem_low_pages_limit(io_tlb_nslabs * + (1 << IO_TLB_SHIFT), 0x100000000); if (!io_tlb_start) panic("Cannot allocate SWIOTLB buffer"); io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 82bd884..3b03b0b 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -43,7 +43,7 @@ typedef struct bootmem_data { extern unsigned long __init bootmem_bootmap_pages (unsigned long); extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend); extern void __init free_bootmem (unsigned long addr, unsigned long size); -extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal); +extern void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal, unsigned long limit); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE extern void __init reserve_bootmem (unsigned long addr, unsigned long size); #define alloc_bootmem(x) \ @@ -54,6 +54,16 @@ extern void __init reserve_bootmem (unsigned long addr, unsigned long size); __alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low_pages(x) \ __alloc_bootmem((x), PAGE_SIZE, 0) + +#define alloc_bootmem_limit(x, limit) \ + __alloc_bootmem_limit((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_limit(x, limit) \ + __alloc_bootmem_limit((x), SMP_CACHE_BYTES, 0, (limit)) +#define alloc_bootmem_pages_limit(x, limit) \ + __alloc_bootmem_limit((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_pages_limit(x, limit) \ + __alloc_bootmem_limit((x), PAGE_SIZE, 0, (limit)) + #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ extern unsigned long __init free_all_bootmem (void); @@ -61,7 +71,7 @@ extern unsigned long __init init_bootmem_node (pg_data_t *pgdat, unsigned long f extern void __init reserve_bootmem_node (pg_data_t *pgdat, unsigned long physaddr, unsigned long size); extern void __init free_bootmem_node (pg_data_t *pgdat, unsigned long addr, unsigned long size); extern unsigned long __init free_all_bootmem_node (pg_data_t *pgdat); -extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal); +extern void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE #define alloc_bootmem_node(pgdat, x) \ __alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) @@ -69,6 +79,14 @@ extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low_pages_node(pgdat, x) \ __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0) + +#define alloc_bootmem_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_pages_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_pages_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, 0, (limit)) + #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ #ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP @@ -105,5 +123,15 @@ extern void *__init alloc_large_system_hash(const char *tablename, #endif extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */ +static inline void *__alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal) +{ + return __alloc_bootmem_limit(size, align, goal, 0); +} + +static inline void *__alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, + unsigned long goal) +{ + return __alloc_bootmem_node_limit(pgdat, size, align, goal, 0); +} #endif /* _LINUX_BOOTMEM_H */ diff --git a/mm/bootmem.c b/mm/bootmem.c index c1330cc..a58699b 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -154,10 +154,10 @@ static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, */ static void * __init __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, - unsigned long align, unsigned long goal) + unsigned long align, unsigned long goal, unsigned long limit) { unsigned long offset, remaining_size, areasize, preferred; - unsigned long i, start = 0, incr, eidx; + unsigned long i, start = 0, incr, eidx, end_pfn = bdata->node_low_pfn; void *ret; if(!size) { @@ -166,7 +166,14 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, } BUG_ON(align & (align-1)); - eidx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT); + if (limit && bdata->node_boot_start >= limit) + return NULL; + + limit >>=PAGE_SHIFT; + if (limit && end_pfn > limit) + end_pfn = limit; + + eidx = end_pfn - (bdata->node_boot_start >> PAGE_SHIFT); offset = 0; if (align && (bdata->node_boot_start & (align - 1UL)) != 0) @@ -178,11 +185,12 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, * first, then we try to allocate lower pages. */ if (goal && (goal >= bdata->node_boot_start) && - ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) { + ((goal >> PAGE_SHIFT) < end_pfn)) { preferred = goal - bdata->node_boot_start; if (bdata->last_success >= preferred) - preferred = bdata->last_success; + if (!limit || (limit && limit > bdata->last_success)) + preferred = bdata->last_success; } else preferred = 0; @@ -382,14 +390,15 @@ unsigned long __init free_all_bootmem (void) return(free_all_bootmem_core(NODE_DATA(0))); } -void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal) +void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal, + unsigned long limit) { pg_data_t *pgdat = pgdat_list; void *ptr; for_each_pgdat(pgdat) if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, - align, goal))) + align, goal, limit))) return(ptr); /* @@ -400,14 +409,16 @@ void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned return NULL; } -void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) + +void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align, + unsigned long goal, unsigned long limit) { void *ptr; - ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal); + ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit); if (ptr) return (ptr); - return __alloc_bootmem(size, align, goal); + return __alloc_bootmem_limit(size, align, goal, limit); } -- cgit v0.10.2 From bf3f81b3f755fe3fced2aaac5cb3ecb4b541f41c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 20 Oct 2005 08:34:56 +1000 Subject: [PATCH] ppc64: update defconfigs Signed-off-by: Paul Mackerras Signed-off-by: Linus Torvalds diff --git a/arch/ppc64/configs/bpa_defconfig b/arch/ppc64/configs/bpa_defconfig index 46c5da4..67ffecb 100644 --- a/arch/ppc64/configs/bpa_defconfig +++ b/arch/ppc64/configs/bpa_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:12:19 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:29:10 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set @@ -36,6 +37,7 @@ CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -95,6 +97,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # CONFIG_NUMA is not set CONFIG_SCHED_SMT=y CONFIG_PREEMPT_NONE=y @@ -110,17 +113,18 @@ CONFIG_PPC_RTAS=y CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y # CONFIG_PCI_DEBUG is not set # @@ -132,8 +136,6 @@ CONFIG_PCI_NAMES=y # PCI Hotplug Support # # CONFIG_HOTPLUG_PCI is not set -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set # # Networking @@ -163,8 +165,8 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set CONFIG_INET_TUNNEL=y -CONFIG_IP_TCPDIAG=y -CONFIG_IP_TCPDIAG_IPV6=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -181,6 +183,7 @@ CONFIG_INET6_TUNNEL=m CONFIG_IPV6_TUNNEL=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set # # IP: Netfilter Configuration @@ -188,11 +191,14 @@ CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=y # CONFIG_IP_NF_CT_ACCT is not set # CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set CONFIG_IP_NF_CT_PROTO_SCTP=y CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m @@ -216,13 +222,16 @@ CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_REALM=m CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_STRING=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -240,6 +249,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m @@ -251,6 +261,12 @@ CONFIG_IP_NF_ARP_MANGLE=m # # CONFIG_IP6_NF_QUEUE is not set # CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_IP6_NF_TARGET_NFQUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set # # SCTP Configuration (EXPERIMENTAL) @@ -278,6 +294,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -292,6 +309,11 @@ CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -322,7 +344,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=131072 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -395,6 +416,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -436,12 +458,18 @@ CONFIG_NETDEVICES=y # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # @@ -462,15 +490,18 @@ CONFIG_E1000=m # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set CONFIG_SKGE=m # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set +# CONFIG_SPIDER_NET is not set # CONFIG_MV643XX_ETH is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -552,6 +583,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set # CONFIG_MOXA_SMARTIO is not set # CONFIG_ISI is not set # CONFIG_SYNCLINK is not set @@ -642,7 +674,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_ISA is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -656,7 +687,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -683,12 +713,17 @@ CONFIG_I2C_ALGOBIT=y # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -756,10 +791,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -768,6 +799,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -794,13 +826,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -# CONFIG_TMPFS_SECURITY is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -846,6 +876,7 @@ CONFIG_SUNRPC=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -923,6 +954,7 @@ CONFIG_NLS_ISO8859_15=m CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=15 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -981,7 +1013,12 @@ CONFIG_CRYPTO_DEFLATE=m # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig index fc83d93..6323065 100644 --- a/arch/ppc64/configs/g5_defconfig +++ b/arch/ppc64/configs/g5_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:16:59 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:30:23 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -37,6 +38,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -97,6 +99,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # CONFIG_NUMA is not set # CONFIG_SCHED_SMT is not set CONFIG_PREEMPT_NONE=y @@ -109,19 +112,20 @@ CONFIG_HZ_250=y CONFIG_HZ=250 CONFIG_GENERIC_HARDIRQS=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_HOTPLUG_CPU is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y # CONFIG_PCI_DEBUG is not set -# CONFIG_HOTPLUG_CPU is not set # # PCCARD (PCMCIA/CardBus) support @@ -132,8 +136,6 @@ CONFIG_PCI_NAMES=y # PCI Hotplug Support # # CONFIG_HOTPLUG_PCI is not set -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set # # Networking @@ -163,8 +165,8 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m CONFIG_INET_TUNNEL=y -CONFIG_IP_TCPDIAG=m -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -175,6 +177,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set # # IP: Netfilter Configuration @@ -182,11 +185,14 @@ CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CT_ACCT=y CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m @@ -210,14 +216,18 @@ CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_REALM=m CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_CONNBYTES=m CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_STRING=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -235,6 +245,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_TARGET_CONNMARK=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m @@ -244,6 +255,11 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -270,6 +286,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -284,6 +301,11 @@ CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -315,7 +337,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 # CONFIG_CDROM_PKTCDVD_WCACHE is not set @@ -395,6 +416,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -422,6 +444,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -435,10 +458,12 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set CONFIG_SCSI_SATA=y # CONFIG_SCSI_SATA_AHCI is not set CONFIG_SCSI_SATA_SVW=y # CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set # CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_QSTOR is not set @@ -498,6 +523,7 @@ CONFIG_DM_ZERO=m # CONFIG_FUSION is not set # CONFIG_FUSION_SPI is not set # CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -540,7 +566,6 @@ CONFIG_IEEE1394_RAWIO=y # CONFIG_ADB_PMU=y CONFIG_PMAC_SMU=y -# CONFIG_PMAC_BACKLIGHT is not set CONFIG_THERM_PM72=y # @@ -558,12 +583,18 @@ CONFIG_TUN=m # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set CONFIG_SUNGEM=y +# CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # @@ -585,6 +616,7 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set CONFIG_TIGON3=m @@ -594,6 +626,7 @@ CONFIG_TIGON3=m # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -760,8 +793,8 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_ISA is not set CONFIG_I2C_KEYWEST=y +CONFIG_I2C_PMAC_SMU=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -775,7 +808,6 @@ CONFIG_I2C_KEYWEST=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -802,12 +834,17 @@ CONFIG_I2C_KEYWEST=y # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -856,6 +893,7 @@ CONFIG_FB_RADEON_I2C=y # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set @@ -937,6 +975,7 @@ CONFIG_USB_STORAGE_DPCM=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ONETOUCH is not set # # USB Input Devices @@ -956,9 +995,11 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MTOUCH is not set # CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -983,30 +1024,14 @@ CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_USBNET=m - -# -# USB Host-to-Host Cables -# -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_BELKIN=y -CONFIG_USB_GENESYS=y -CONFIG_USB_NET1080=y -CONFIG_USB_PL2301=y -CONFIG_USB_KC2190=y - -# -# Intelligent USB Devices/Gadgets -# -CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_ZAURUS=y -CONFIG_USB_CDCETHER=y - -# -# USB Network Adapters -# -CONFIG_USB_AX8817X=y +# CONFIG_USB_NET_AX8817X is not set +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set CONFIG_USB_MON=y # @@ -1124,16 +1149,12 @@ CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# CONFIG_XFS_FS=m CONFIG_XFS_EXPORT=y -# CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1141,6 +1162,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -1168,14 +1190,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -1225,6 +1244,7 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -1303,6 +1323,7 @@ CONFIG_OPROFILE=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1360,7 +1381,12 @@ CONFIG_CRYPTO_TEST=m # Library routines # CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig index 013d4e0..62e92c7 100644 --- a/arch/ppc64/configs/iSeries_defconfig +++ b/arch/ppc64/configs/iSeries_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:17:02 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:30:56 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -38,6 +39,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -88,6 +90,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # CONFIG_NUMA is not set # CONFIG_SCHED_SMT is not set CONFIG_PREEMPT_NONE=y @@ -101,17 +104,16 @@ CONFIG_HZ=250 CONFIG_GENERIC_HARDIRQS=y CONFIG_LPARCFG=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y # CONFIG_PCI_DEBUG is not set # @@ -152,8 +154,8 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m CONFIG_INET_TUNNEL=y -CONFIG_IP_TCPDIAG=m -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -164,6 +166,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +# CONFIG_NETFILTER_NETLINK is not set # # IP: Netfilter Configuration @@ -171,11 +174,14 @@ CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CT_ACCT=y CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m @@ -199,14 +205,18 @@ CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_REALM=m CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_CONNBYTES=m CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_STRING=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -224,6 +234,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_TARGET_CONNMARK=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m @@ -233,6 +244,11 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -259,6 +275,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -273,6 +290,11 @@ CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -303,7 +325,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -323,6 +344,7 @@ CONFIG_IOSCHED_CFQ=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -350,6 +372,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -363,6 +386,7 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -415,6 +439,7 @@ CONFIG_DM_ZERO=m # CONFIG_FUSION is not set # CONFIG_FUSION_SPI is not set # CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -445,12 +470,18 @@ CONFIG_TUN=m # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # @@ -489,6 +520,7 @@ CONFIG_E1000=m # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set @@ -498,6 +530,7 @@ CONFIG_E1000=m # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -632,7 +665,6 @@ CONFIG_MAX_RAW_DEVS=256 # I2C support # # CONFIG_I2C is not set -# CONFIG_I2C_SENSOR is not set # # Dallas's 1-wire bus @@ -643,12 +675,17 @@ CONFIG_MAX_RAW_DEVS=256 # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -722,16 +759,12 @@ CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# CONFIG_XFS_FS=m CONFIG_XFS_EXPORT=y -# CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -739,6 +772,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -766,14 +800,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -824,6 +855,7 @@ CONFIG_CIFS_POSIX=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -897,6 +929,7 @@ CONFIG_OPROFILE=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -954,7 +987,12 @@ CONFIG_CRYPTO_TEST=m # Library routines # CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig index dd42892..7b480f3 100644 --- a/arch/ppc64/configs/maple_defconfig +++ b/arch/ppc64/configs/maple_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:17:04 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:31:24 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -37,6 +38,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y @@ -97,6 +99,7 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set # CONFIG_NUMA is not set # CONFIG_SCHED_SMT is not set CONFIG_PREEMPT_NONE=y @@ -109,17 +112,18 @@ CONFIG_HZ_250=y CONFIG_HZ=250 CONFIG_GENERIC_HARDIRQS=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y # CONFIG_PCI_DEBUG is not set # @@ -131,8 +135,6 @@ CONFIG_PCI_NAMES=y # PCI Hotplug Support # # CONFIG_HOTPLUG_PCI is not set -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set # # Networking @@ -163,14 +165,19 @@ CONFIG_IP_PNP_DHCP=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_TUNNEL is not set -CONFIG_IP_TCPDIAG=y -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set # CONFIG_NETFILTER is not set # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -196,6 +203,7 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -210,6 +218,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -240,7 +253,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_INITRD is not set -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -313,6 +325,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # @@ -354,12 +367,18 @@ CONFIG_NETDEVICES=y # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # @@ -398,6 +417,7 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set @@ -408,6 +428,7 @@ CONFIG_E1000=y # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set @@ -553,7 +574,6 @@ CONFIG_I2C_AMD8111=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_ISA is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set @@ -567,7 +587,6 @@ CONFIG_I2C_AMD8111=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -594,12 +613,17 @@ CONFIG_I2C_AMD8111=y # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -681,9 +705,11 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_MTOUCH is not set # CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -814,10 +840,6 @@ CONFIG_JBD=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -826,6 +848,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -849,14 +872,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -# CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -898,6 +918,7 @@ CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -975,6 +996,7 @@ CONFIG_NLS_UTF8=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set CONFIG_DEBUG_SLAB=y # CONFIG_DEBUG_SPINLOCK is not set @@ -1034,6 +1056,7 @@ CONFIG_CRYPTO_DES=y # Library routines # CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig index 29f7b80..9f09dff 100644 --- a/arch/ppc64/configs/pSeries_defconfig +++ b/arch/ppc64/configs/pSeries_defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:17:07 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:32:17 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -38,6 +39,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CPUSETS=y +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y @@ -104,6 +106,7 @@ CONFIG_DISCONTIGMEM_MANUAL=y CONFIG_DISCONTIGMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y +# CONFIG_SPARSEMEM_STATIC is not set CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_NODES_SPAN_OTHER_NODES=y CONFIG_NUMA=y @@ -124,19 +127,20 @@ CONFIG_RTAS_FLASH=m CONFIG_SCANLOG=m CONFIG_LPARCFG=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_HOTPLUG_CPU=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y # CONFIG_PCI_DEBUG is not set -CONFIG_HOTPLUG_CPU=y # # PCCARD (PCMCIA/CardBus) support @@ -152,8 +156,6 @@ CONFIG_HOTPLUG_PCI=m # CONFIG_HOTPLUG_PCI_SHPC is not set CONFIG_HOTPLUG_PCI_RPA=m CONFIG_HOTPLUG_PCI_RPA_DLPAR=m -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set # # Networking @@ -183,8 +185,8 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m CONFIG_INET_TUNNEL=y -CONFIG_IP_TCPDIAG=m -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -195,6 +197,9 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m # # IP: Netfilter Configuration @@ -202,11 +207,15 @@ CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CT_ACCT=y CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m @@ -230,14 +239,18 @@ CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_REALM=m CONFIG_IP_NF_MATCH_SCTP=m +# CONFIG_IP_NF_MATCH_DCCP is not set CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_CONNBYTES=m CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_STRING=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -255,6 +268,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_TARGET_CONNMARK=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m @@ -264,6 +278,11 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -290,6 +309,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -304,6 +324,11 @@ CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -342,7 +367,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -416,6 +440,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -443,6 +468,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -456,6 +482,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set @@ -517,6 +544,7 @@ CONFIG_DM_MULTIPATH_EMC=m # CONFIG_FUSION is not set # CONFIG_FUSION_SPI is not set # CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -547,12 +575,18 @@ CONFIG_TUN=m # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=y # CONFIG_TYPHOON is not set @@ -581,6 +615,7 @@ CONFIG_E100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) @@ -594,6 +629,7 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set @@ -604,6 +640,7 @@ CONFIG_TIGON3=y # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set CONFIG_S2IO=m @@ -789,7 +826,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_ISA is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set @@ -804,7 +840,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -831,12 +866,17 @@ CONFIG_I2C_ALGOBIT=y # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -885,6 +925,7 @@ CONFIG_FB_RADEON_I2C=y # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set @@ -982,9 +1023,11 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MTOUCH is not set # CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -1057,7 +1100,8 @@ CONFIG_USB_MON=y # InfiniBand support # CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_USER_VERBS=m +# CONFIG_INFINIBAND_USER_MAD is not set +# CONFIG_INFINIBAND_USER_ACCESS is not set CONFIG_INFINIBAND_MTHCA=m # CONFIG_INFINIBAND_MTHCA_DEBUG is not set CONFIG_INFINIBAND_IPOIB=m @@ -1095,16 +1139,12 @@ CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# CONFIG_XFS_FS=m CONFIG_XFS_EXPORT=y -# CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1112,6 +1152,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -1139,14 +1180,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -1197,6 +1235,7 @@ CONFIG_CIFS_POSIX=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -1261,6 +1300,7 @@ CONFIG_OPROFILE=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1320,7 +1360,12 @@ CONFIG_CRYPTO_TEST=m # Library routines # CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig index 7cb4750..37c157c 100644 --- a/arch/ppc64/defconfig +++ b/arch/ppc64/defconfig @@ -1,17 +1,17 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.13-rc6 -# Mon Aug 8 14:16:54 2005 +# Linux kernel version: 2.6.14-rc4 +# Thu Oct 20 08:28:33 2005 # CONFIG_64BIT=y CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_FORCE_MAX_ZONEORDER=13 # @@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -37,6 +38,7 @@ CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CPUSETS=y +CONFIG_INITRAMFS_SOURCE="" # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set @@ -106,6 +108,7 @@ CONFIG_DISCONTIGMEM_MANUAL=y CONFIG_DISCONTIGMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y +# CONFIG_SPARSEMEM_STATIC is not set CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_NODES_SPAN_OTHER_NODES=y # CONFIG_NUMA is not set @@ -126,19 +129,20 @@ CONFIG_RTAS_FLASH=m CONFIG_SCANLOG=m CONFIG_LPARCFG=y CONFIG_SECCOMP=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_HOTPLUG_CPU=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set CONFIG_ISA_DMA_API=y # -# General setup +# Bus Options # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m # CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set # CONFIG_PCI_DEBUG is not set -CONFIG_HOTPLUG_CPU=y # # PCCARD (PCMCIA/CardBus) support @@ -154,8 +158,6 @@ CONFIG_HOTPLUG_PCI=m # CONFIG_HOTPLUG_PCI_SHPC is not set CONFIG_HOTPLUG_PCI_RPA=m CONFIG_HOTPLUG_PCI_RPA_DLPAR=m -CONFIG_PROC_DEVICETREE=y -# CONFIG_CMDLINE_BOOL is not set # # Networking @@ -185,8 +187,8 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m CONFIG_INET_TUNNEL=y -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -197,6 +199,9 @@ CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m # # IP: Netfilter Configuration @@ -204,11 +209,15 @@ CONFIG_NETFILTER=y CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_CT_ACCT=y CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m CONFIG_IP_NF_CT_PROTO_SCTP=m CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m @@ -232,14 +241,18 @@ CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_REALM=m CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_DCCP=m CONFIG_IP_NF_MATCH_COMMENT=m CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_CONNBYTES=m CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_MATCH_STRING=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_TARGET_NFQUEUE=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m @@ -257,6 +270,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_TARGET_CONNMARK=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m @@ -266,6 +280,11 @@ CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set @@ -292,6 +311,7 @@ CONFIG_NET_CLS_ROUTE=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # # Device Drivers @@ -306,6 +326,11 @@ CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set # +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -344,7 +369,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" # CONFIG_CDROM_PKTCDVD is not set # @@ -422,6 +446,7 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -449,6 +474,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -462,10 +488,12 @@ CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_AIC79XX is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set CONFIG_SCSI_SATA=y # CONFIG_SCSI_SATA_AHCI is not set CONFIG_SCSI_SATA_SVW=y # CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set # CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_QSTOR is not set @@ -535,6 +563,7 @@ CONFIG_DM_MULTIPATH_EMC=m # CONFIG_FUSION is not set # CONFIG_FUSION_SPI is not set # CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -578,7 +607,6 @@ CONFIG_IEEE1394_AMDTP=m # CONFIG_ADB_PMU=y CONFIG_PMAC_SMU=y -# CONFIG_PMAC_BACKLIGHT is not set CONFIG_THERM_PM72=y # @@ -596,12 +624,18 @@ CONFIG_TUN=m # CONFIG_ARCNET is not set # +# PHY device support +# +# CONFIG_PHYLIB is not set + +# # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set CONFIG_SUNGEM=y +# CONFIG_CASSINI is not set CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=y # CONFIG_TYPHOON is not set @@ -630,6 +664,7 @@ CONFIG_E100=y # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) @@ -643,16 +678,19 @@ CONFIG_E1000=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set +# CONFIG_SPIDER_NET is not set # CONFIG_MV643XX_ETH is not set # # Ethernet (10000 Mbit) # +# CONFIG_CHELSIO_T1 is not set CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set # CONFIG_S2IO is not set @@ -838,8 +876,8 @@ CONFIG_I2C_AMD8111=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_ISA is not set CONFIG_I2C_KEYWEST=y +CONFIG_I2C_PMAC_SMU=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set @@ -854,7 +892,6 @@ CONFIG_I2C_KEYWEST=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -881,12 +918,17 @@ CONFIG_I2C_KEYWEST=y # Hardware Monitoring support # # CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set # # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -939,6 +981,7 @@ CONFIG_FB_RADEON_I2C=y # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_CYBLA is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set @@ -1020,6 +1063,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set # # USB Input Devices @@ -1036,9 +1080,11 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MTOUCH is not set # CONFIG_USB_ITMTOUCH is not set # CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set # CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -1111,7 +1157,8 @@ CONFIG_USB_PEGASUS=y # InfiniBand support # CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_USER_VERBS=m +# CONFIG_INFINIBAND_USER_MAD is not set +# CONFIG_INFINIBAND_USER_ACCESS is not set CONFIG_INFINIBAND_MTHCA=m # CONFIG_INFINIBAND_MTHCA_DEBUG is not set CONFIG_INFINIBAND_IPOIB=m @@ -1149,16 +1196,12 @@ CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y - -# -# XFS support -# CONFIG_XFS_FS=m CONFIG_XFS_EXPORT=y -# CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y @@ -1166,6 +1209,7 @@ CONFIG_INOTIFY=y CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -1192,14 +1236,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y -CONFIG_TMPFS_XATTR=y -CONFIG_TMPFS_SECURITY=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -1250,6 +1291,7 @@ CONFIG_CIFS_POSIX=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set # # Partition Types @@ -1328,6 +1370,7 @@ CONFIG_OPROFILE=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1387,7 +1430,12 @@ CONFIG_CRYPTO_TEST=m # Library routines # CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m -- cgit v0.10.2 From 461a0ffbec1bcea896bd5daf1a98a18232a1e9c7 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 19 Oct 2005 08:22:13 -0400 Subject: [PATCH] scsi_error thread exits in TASK_INTERRUPTIBLE state. Found in the -rt patch set. The scsi_error thread likely will be in the TASK_INTERRUPTIBLE state upon exit. This patch fixes this bug. Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ad53421..52b348c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1645,6 +1645,8 @@ int scsi_error_handler(void *data) set_current_state(TASK_INTERRUPTIBLE); } + __set_current_state(TASK_RUNNING); + SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" " exiting\n",shost->host_no)); -- cgit v0.10.2 From 450da6ca97185830315d21c06e46e232618e0fa6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Oct 2005 22:45:17 +0100 Subject: [PATCH] build fix for uml/amd64 Missing half of the [PATCH] uml: Fix sysrq-r support for skas mode We need to remove these (UPT_[DEFG]S) from the read side as well as the write one - otherwise it simply won't build. Signed-off-by: Al Viro Acked-by: Paolo 'Blaisorblade' Giarrusso Acked-by: Jeff Dike Signed-off-by: Linus Torvalds diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h index 8f06567..8d353f0 100644 --- a/arch/um/include/sysdep-x86_64/ptrace.h +++ b/arch/um/include/sysdep-x86_64/ptrace.h @@ -183,10 +183,6 @@ struct syscall_args { case RBP: val = UPT_RBP(regs); break; \ case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ case CS: val = UPT_CS(regs); break; \ - case DS: val = UPT_DS(regs); break; \ - case ES: val = UPT_ES(regs); break; \ - case FS: val = UPT_FS(regs); break; \ - case GS: val = UPT_GS(regs); break; \ case EFLAGS: val = UPT_EFLAGS(regs); break; \ default : \ panic("Bad register in UPT_REG : %d\n", reg); \ -- cgit v0.10.2 From 93918e9afc76717176e9e114e79cdbb602a45ae8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 19 Oct 2005 23:23:05 -0700 Subject: Linux v2.6.14-rc5 The -rc4 release was supposed to be the last -rc, but here goes. The RCU fixes and the swiotlb changes need an -rc for final testing. diff --git a/Makefile b/Makefile index 91de6be..4a7000e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 14 -EXTRAVERSION =-rc4 +EXTRAVERSION =-rc5 NAME=Affluent Albatross # *DOCUMENTATION* -- cgit v0.10.2 From ac9b9c667c2e1194e22ebe0a441ae1c37aaa9b90 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Thu, 20 Oct 2005 16:24:28 +0100 Subject: [PATCH] Fix handling spurious page fault for hugetlb region This reverts commit 3359b54c8c07338f3a863d1109b42eebccdcf379 and replaces it with a cleaner version that is purely based on page table operations, so that the synchronization between inode size and hugetlb mappings becomes moot. Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 42cb7d70..d664330 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -25,6 +25,8 @@ int is_hugepage_mem_enough(size_t); unsigned long hugetlb_total_pages(void); struct page *alloc_huge_page(void); void free_huge_page(struct page *); +int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access); extern unsigned long max_huge_pages; extern const unsigned long hugetlb_zero, hugetlb_infinity; @@ -99,6 +101,7 @@ static inline unsigned long hugetlb_total_pages(void) do { } while (0) #define alloc_huge_page() ({ NULL; }) #define free_huge_page(p) ({ (void)(p); BUG(); }) +#define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) #ifndef HPAGE_MASK #define HPAGE_MASK 0 /* Keep the compiler happy */ @@ -155,24 +158,11 @@ static inline void set_file_hugepages(struct file *file) { file->f_op = &hugetlbfs_file_operations; } - -static inline int valid_hugetlb_file_off(struct vm_area_struct *vma, - unsigned long address) -{ - struct inode *inode = vma->vm_file->f_dentry->d_inode; - loff_t file_off = address - vma->vm_start; - - file_off += (vma->vm_pgoff << PAGE_SHIFT); - - return (file_off < inode->i_size); -} - #else /* !CONFIG_HUGETLBFS */ #define is_file_hugepages(file) 0 #define set_file_hugepages(file) BUG() #define hugetlb_zero_setup(size) ERR_PTR(-ENOSYS) -#define valid_hugetlb_file_off(vma, address) 0 #endif /* !CONFIG_HUGETLBFS */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a1b30d4..61d3806 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -394,6 +394,28 @@ out: return ret; } +/* + * On ia64 at least, it is possible to receive a hugetlb fault from a + * stale zero entry left in the TLB from earlier hardware prefetching. + * Low-level arch code should already have flushed the stale entry as + * part of its fault handling, but we do need to accept this minor fault + * and return successfully. Whereas the "normal" case is that this is + * an access to a hugetlb page which has been truncated off since mmap. + */ +int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access) +{ + int ret = VM_FAULT_SIGBUS; + pte_t *pte; + + spin_lock(&mm->page_table_lock); + pte = huge_pte_offset(mm, address); + if (pte && !pte_none(*pte)) + ret = VM_FAULT_MINOR; + spin_unlock(&mm->page_table_lock); + return ret; +} + int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page **pages, struct vm_area_struct **vmas, unsigned long *position, int *length, int i) diff --git a/mm/memory.c b/mm/memory.c index 8c88b97..1db40e9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2045,18 +2045,8 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, inc_page_state(pgfault); - if (unlikely(is_vm_hugetlb_page(vma))) { - if (valid_hugetlb_file_off(vma, address)) - /* We get here only if there was a stale(zero) TLB entry - * (because of HW prefetching). - * Low-level arch code (if needed) should have already - * purged the stale entry as part of this fault handling. - * Here we just return. - */ - return VM_FAULT_MINOR; - else - return VM_FAULT_SIGBUS; /* mapping truncation does this. */ - } + if (unlikely(is_vm_hugetlb_page(vma))) + return hugetlb_fault(mm, vma, address, write_access); /* * We need the page table lock to synchronize with kswapd -- cgit v0.10.2