From 9632051963cb6e6f7412990f8b962209b9334e13 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 29 Nov 2005 22:27:14 +0100 Subject: [PATCH] hwmon: w83792d fix unused fan pins 1. This patch add check for fan4,5,6,7 and do not create device file if their pins are not configured as fan. 2. Fix the issue that can not set fan divisor to 128. 3. Fix the index out of bounds bug in w83792d_detect function. Signed-off-by: Yuan Mu Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83792d.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 4be59dbb78c4..1ba072630361 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -193,6 +193,7 @@ static const u8 W83792D_REG_LEVELS[3][4] = { 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */ }; +#define W83792D_REG_GPIO_EN 0x1A #define W83792D_REG_CONFIG 0x40 #define W83792D_REG_VID_FANDIV 0x47 #define W83792D_REG_CHIPID 0x49 @@ -257,7 +258,7 @@ DIV_TO_REG(long val) { int i; val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { if (val == 0) break; val >>= 1; @@ -1282,8 +1283,8 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) w83792d_init_client(new_client); /* A few vars need to be filled upon startup */ - for (i = 1; i <= 7; i++) { - data->fan_min[i - 1] = w83792d_read_value(new_client, + for (i = 0; i < 7; i++) { + data->fan_min[i] = w83792d_read_value(new_client, W83792D_REG_FAN_MIN[i]); } @@ -1306,10 +1307,20 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) device_create_file_fan(new_client, 1); device_create_file_fan(new_client, 2); device_create_file_fan(new_client, 3); - device_create_file_fan(new_client, 4); - device_create_file_fan(new_client, 5); - device_create_file_fan(new_client, 6); - device_create_file_fan(new_client, 7); + + /* Read GPIO enable register to check if pins for fan 4,5 are used as + GPIO */ + val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); + if (!(val1 & 0x40)) + device_create_file_fan(new_client, 4); + if (!(val1 & 0x20)) + device_create_file_fan(new_client, 5); + + val1 = w83792d_read_value(new_client, W83792D_REG_PIN); + if (val1 & 0x40) + device_create_file_fan(new_client, 6); + if (val1 & 0x04) + device_create_file_fan(new_client, 7); device_create_file_temp1(new_client); /* Temp1 */ device_create_file_temp_add(new_client, 2); /* Temp2 */ -- cgit v1.2.3 From c9d6073fb3cda856132dd544d537679f9715436c Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Thu, 24 Nov 2005 20:41:06 +1100 Subject: [PATCH] pci_ids.h: remove duplicate entries G'day Albert, Andrew, commit 4fb80634d30f5e639a92b78c8f215f96a61ba8c7 Author: Albert Lee Date: Thu May 12 15:49:21 2005 -0400 duplicates symbols already appearing in pci_ids.h, appended patch removes them again :o) From: Grant Coady pci_ids: commit 4fb80634d30f5e639a92b78c8f215f96a61ba8c7 duplicated a couple existing symbols in pci_ids.h, remove them. Signed-off-by: Grant Coady Signed-off-by: Greg Kroah-Hartman --- include/linux/pci_ids.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 1e737e269db9..53e3293051d4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -387,7 +387,6 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 @@ -489,8 +488,6 @@ #define PCI_DEVICE_ID_AMD_8151_0 0x7454 #define PCI_DEVICE_ID_AMD_8131_APIC 0x7450 -#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A - #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 -- cgit v1.2.3 From 620948a01c71060a32611bc2f792f58a88cf28b1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 28 Nov 2005 15:22:55 -0500 Subject: [PATCH] USB: documentation update This patch (as611) fixes a minor mistake and misspelling in the USB documentation. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/error-codes.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt index 1e36f1661cd0..867f4c38f356 100644 --- a/Documentation/usb/error-codes.txt +++ b/Documentation/usb/error-codes.txt @@ -46,8 +46,9 @@ USB-specific: -EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable in the current interface altsetting. - (b) ISO packet is biger than endpoint maxpacket - (c) requested data transfer size is invalid (negative) + (b) ISO packet is larger than the endpoint maxpacket. + (c) requested data transfer length is invalid: negative + or too large for the host controller. -ENOSPC This request would overcommit the usb bandwidth reserved for periodic transfers (interrupt, isochronous). -- cgit v1.2.3 From d3420ba4930d61f4ec4abc046765de274182b4ed Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 28 Nov 2005 13:44:52 -0500 Subject: [PATCH] Additional device ID for Conexant AccessRunner USB driver Reported as working in Fedora bugzilla by Petr. From: Petr Tuma Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 79861ee12a29..9d59dc62e6d2 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -787,6 +787,9 @@ static const struct usb_device_id cxacru_usb_ids[] = { { /* V = Conexant P = ADSL modem (Hasbani project) */ USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00 }, + { /* V = Conexant P = ADSL modem (Well PTI-800 */ + USB_DEVICE(0x0572, 0xcb02), .driver_info = (unsigned long) &cxacru_cb00 + }, { /* V = Conexant P = ADSL modem */ USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 }, -- cgit v1.2.3 From 8de98402652c01839ae321be6cb3054cf5735d83 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 25 Nov 2005 09:59:46 +1100 Subject: [PATCH] USB: Fix USB suspend/resume crasher (#2) This patch closes the IRQ race and makes various other OHCI & EHCI code path safer vs. suspend/resume. I've been able to (finally !) successfully suspend and resume various Mac models, with or without USB mouse plugged, or plugging while asleep, or unplugging while asleep etc... all without a crash. Alan, please verify the UHCI bit I did, I only verified that it builds. It's very simple so I wouldn't expect any issue there. If you aren't confident, then just drop the hunks that change uhci-hcd.c I also made the patch a little bit more "safer" by making sure the store to the interrupt register that disables interrupts is not posted before I set the flag and drop the spinlock. Without this patch, you cannot reliably sleep/wakeup any recent Mac, and I suspect PCs have some more sneaky issues too (they don't frankly crash with machine checks because x86 tend to silently swallow PCI errors but that won't last afaik, at least PCI Express will blow up in those situations, but the USB code may still misbehave). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 3 ++- drivers/usb/core/hcd.c | 15 ++++++++++----- drivers/usb/core/hcd.h | 7 ++++++- drivers/usb/host/ehci-pci.c | 27 ++++++++++++++++++++++++++- drivers/usb/host/ehci-q.c | 24 ++++++++++++++++-------- drivers/usb/host/ehci-sched.c | 18 ++++++++++++++++-- drivers/usb/host/ohci-hcd.c | 6 +++++- drivers/usb/host/ohci-hub.c | 24 ++++++++++++++++++++---- drivers/usb/host/ohci-pci.c | 27 +++++++++++++++++++++++++-- drivers/usb/host/uhci-hcd.c | 6 ++++++ 10 files changed, 132 insertions(+), 25 deletions(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5131d88e8c5b..29b5b2a6e183 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -219,6 +219,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) goto done; } } + synchronize_irq(dev->irq); /* FIXME until the generic PM interfaces change a lot more, this * can't use PCI D1 and D2 states. For example, the confusion @@ -392,7 +393,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) dev->dev.power.power_state = PMSG_ON; - hcd->saw_irq = 0; + clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); if (hcd->driver->resume) { retval = hcd->driver->resume(hcd); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5e5f65a475ab..da24c31ee00d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1315,11 +1315,12 @@ static int hcd_unlink_urb (struct urb *urb, int status) * finish unlinking the initial failed usb_set_address() * or device descriptor fetch. */ - if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { + if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) + && hcd->self.root_hub != urb->dev) { dev_warn (hcd->self.controller, "Unlink after no-IRQ? " "Controller is probably using the wrong IRQ." "\n"); - hcd->saw_irq = 1; + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); } urb->status = status; @@ -1649,13 +1650,15 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) struct usb_hcd *hcd = __hcd; int start = hcd->state; - if (start == HC_STATE_HALT) + if (unlikely(start == HC_STATE_HALT || + !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) return IRQ_NONE; if (hcd->driver->irq (hcd, r) == IRQ_NONE) return IRQ_NONE; - hcd->saw_irq = 1; - if (hcd->state == HC_STATE_HALT) + set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (unlikely(hcd->state == HC_STATE_HALT)) usb_hc_died (hcd); return IRQ_HANDLED; } @@ -1768,6 +1771,8 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_info(hcd->self.controller, "%s\n", hcd->product_desc); + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* till now HC has been in an indeterminate state ... */ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { dev_err(hcd->self.controller, "can't reset\n"); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 24a62a2ff86d..c8a1b350e2cf 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -72,7 +72,12 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ * hardware info/state */ const struct hc_driver *driver; /* hw-specific hooks */ - unsigned saw_irq : 1; + + /* Flags that need to be manipulated atomically */ + unsigned long flags; +#define HCD_FLAG_HW_ACCESSIBLE 0x00000001 +#define HCD_FLAG_SAW_IRQ 0x00000002 + unsigned can_wakeup:1; /* hw supports wakeup? */ unsigned remote_wakeup:1;/* sw should use wakeup? */ unsigned rh_registered:1;/* is root hub registered? */ diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 441c26064b44..14fff5714c1e 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -228,14 +228,36 @@ static int ehci_pci_reset(struct usb_hcd *hcd) static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); + unsigned long flags; + int rc = 0; if (time_before(jiffies, ehci->next_statechange)) msleep(10); + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave (&ehci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + writel (0, &ehci->regs->intr_enable); + (void)readl(&ehci->regs->intr_enable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ehci->lock, flags); + // could save FLADJ in case of Vaux power loss // ... we'd only use it to handle clock skew - return 0; + return rc; } static int ehci_pci_resume(struct usb_hcd *hcd) @@ -251,6 +273,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd) if (time_before(jiffies, ehci->next_statechange)) msleep(100); + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + /* If CF is clear, we lost PCI Vaux power and need to restart. */ if (readl(&ehci->regs->configured_flag) != FLAG_CF) goto restart; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5bb872c3496d..bf03ec0d8ee2 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -912,6 +912,7 @@ submit_async ( int epnum; unsigned long flags; struct ehci_qh *qh = NULL; + int rc = 0; qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); epnum = ep->desc.bEndpointAddress; @@ -926,21 +927,28 @@ submit_async ( #endif spin_lock_irqsave (&ehci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) { + rc = -ESHUTDOWN; + goto done; + } + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); + if (unlikely(qh == NULL)) { + rc = -ENOMEM; + goto done; + } /* Control/bulk operations through TTs don't need scheduling, * the HC and TT handle it when the TT has a buffer ready. */ - if (likely (qh != NULL)) { - if (likely (qh->qh_state == QH_STATE_IDLE)) - qh_link_async (ehci, qh_get (qh)); - } + if (likely (qh->qh_state == QH_STATE_IDLE)) + qh_link_async (ehci, qh_get (qh)); + done: spin_unlock_irqrestore (&ehci->lock, flags); - if (unlikely (qh == NULL)) { + if (unlikely (qh == NULL)) qtd_list_free (ehci, urb, qtd_list); - return -ENOMEM; - } - return 0; + return rc; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f0c8aa1ccd5d..57e77374d228 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -602,6 +602,12 @@ static int intr_submit ( spin_lock_irqsave (&ehci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) { + status = -ESHUTDOWN; + goto done; + } + /* get qh and force any scheduling errors */ INIT_LIST_HEAD (&empty); qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); @@ -1456,7 +1462,11 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - status = iso_stream_schedule (ehci, urb, stream); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) + status = -ESHUTDOWN; + else + status = iso_stream_schedule (ehci, urb, stream); if (likely (status == 0)) itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); spin_unlock_irqrestore (&ehci->lock, flags); @@ -1815,7 +1825,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - status = iso_stream_schedule (ehci, urb, stream); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, + &ehci_to_hcd(ehci)->flags))) + status = -ESHUTDOWN; + else + status = iso_stream_schedule (ehci, urb, stream); if (status == 0) sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); spin_unlock_irqrestore (&ehci->lock, flags); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5c0c6c8a7a82..bf1d9abc07ac 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -115,7 +115,7 @@ /*-------------------------------------------------------------------------*/ -// #define OHCI_VERBOSE_DEBUG /* not always helpful */ +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR @@ -253,6 +253,10 @@ static int ohci_urb_enqueue ( spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ + if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + retval = -ENODEV; + goto fail; + } if (!HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; goto fail; diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index e01e77bc324b..72e3b12a1926 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -53,6 +53,11 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) spin_lock_irqsave (&ohci->lock, flags); + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + spin_unlock_irqrestore (&ohci->lock, flags); + return -ESHUTDOWN; + } + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_RESUME: @@ -140,11 +145,19 @@ static int ohci_bus_resume (struct usb_hcd *hcd) struct ohci_hcd *ohci = hcd_to_ohci (hcd); u32 temp, enables; int status = -EINPROGRESS; + unsigned long flags; if (time_before (jiffies, ohci->next_statechange)) msleep(5); - spin_lock_irq (&ohci->lock); + spin_lock_irqsave (&ohci->lock, flags); + + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + spin_unlock_irqrestore (&ohci->lock, flags); + return -ESHUTDOWN; + } + + ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { @@ -179,7 +192,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) ohci_dbg (ohci, "lost power\n"); status = -EBUSY; } - spin_unlock_irq (&ohci->lock); + spin_unlock_irqrestore (&ohci->lock, flags); if (status == -EBUSY) { (void) ohci_init (ohci); return ohci_restart (ohci); @@ -297,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER - || !HC_IS_RUNNING(hcd->state)) { + if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER + || !HC_IS_RUNNING(hcd->state))) { can_suspend = 0; goto done; } @@ -508,6 +521,9 @@ static int ohci_hub_control ( u32 temp; int retval = 0; + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + return -ESHUTDOWN; + switch (typeReq) { case ClearHubFeature: switch (wValue) { diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 5f22e6590cd1..1b09dde068e1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -105,13 +105,36 @@ ohci_pci_start (struct usb_hcd *hcd) static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) { - /* root hub was already suspended */ - return 0; + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + int rc = 0; + + /* Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave (&ohci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED) { + rc = -EINVAL; + goto bail; + } + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + bail: + spin_unlock_irqrestore (&ohci->lock, flags); + + return rc; } static int ohci_pci_resume (struct usb_hcd *hcd) { + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); usb_hcd_resume_root_hub(hcd); return 0; } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d33ce3982a5f..ed550132db0b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -717,6 +717,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) * at the source, so we must turn off PIRQ. */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); uhci->hc_inaccessible = 1; hcd->poll_rh = 0; @@ -733,6 +734,11 @@ static int uhci_resume(struct usb_hcd *hcd) dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); + /* We aren't in D3 state anymore, we do that even if dead as I + * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0 + */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ return 0; spin_lock_irq(&uhci->lock); -- cgit v1.2.3 From 8926bfa7462d4c3f8b05cca929e0c4bcde93ae38 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 28 Nov 2005 08:40:38 -0800 Subject: [PATCH] USB: ehci fixups Rename the EHCI "reset" routine so it better matches what it does (setup); and move the one-time data structure setup earlier, before doing anything that implicitly relies on it having been completed already. From: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 14fff5714c1e..13f73a836e45 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -121,8 +121,8 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } -/* called by khubd or root hub (re)init threads; leaves HC in halt state */ -static int ehci_pci_reset(struct usb_hcd *hcd) +/* called during probe() after chip reset completes */ +static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); @@ -141,6 +141,11 @@ static int ehci_pci_reset(struct usb_hcd *hcd) if (retval) return retval; + /* data structure init */ + retval = ehci_init(hcd); + if (retval) + return retval; + /* NOTE: only the parts below this line are PCI-specific */ switch (pdev->vendor) { @@ -154,7 +159,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) /* AMD8111 EHCI doesn't work, according to AMD errata */ if (pdev->device == 0x7463) { ehci_info(ehci, "ignoring AMD8111 (errata)\n"); - return -EIO; + retval = -EIO; + goto done; } break; case PCI_VENDOR_ID_NVIDIA: @@ -207,9 +213,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ retval = ehci_pci_reinit(ehci, pdev); - - /* finish init */ - return ehci_init(hcd); +done: + return retval; } /*-------------------------------------------------------------------------*/ @@ -344,7 +349,7 @@ static const struct hc_driver ehci_pci_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_pci_reset, + .reset = ehci_pci_setup, .start = ehci_run, #ifdef CONFIG_PM .suspend = ehci_pci_suspend, -- cgit v1.2.3 From c801147c5a103eec864afee348c4ee3fdb0f380c Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 30 Nov 2005 15:32:59 +0100 Subject: [PATCH] SiS DRM: Fix possible NULL dereference This fixes a NULL pointer reference in DRM. The SiS driver tries to allocate a big chunk of memory, but the return value is never checked. Reported in Novell bugzilla #132271: https://bugzilla.novell.com/show_bug.cgi?id=132271 Signed-off-by: Takashi Iwai Signed-off-by: Linus Torvalds --- drivers/char/drm/drm_context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index bdd168d88f49..bd958d69a2ac 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c @@ -432,7 +432,10 @@ int drm_addctx(struct inode *inode, struct file *filp, if (ctx.handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_ctor) - dev->driver->context_ctor(dev, ctx.handle); + if (!dev->driver->context_ctor(dev, ctx.handle)) { + DRM_DEBUG( "Running out of ctxs or memory.\n"); + return -ENOMEM; + } } ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST); -- cgit v1.2.3 From a145dd411eb28c83ee4bb68b66f62c326c0f764e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 30 Nov 2005 09:35:19 -0800 Subject: VM: add "vm_insert_page()" function This is what a lot of drivers will actually want to use to insert individual pages into a user VMA. It doesn't have the old PageReserved restrictions of remap_pfn_range(), and it doesn't complain about partial remappings. The page you insert needs to be a nice clean kernel allocation, so you can't insert arbitrary page mappings with this, but that's not what people want. Signed-off-by: Linus Torvalds --- include/linux/mm.h | 1 + mm/memory.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0e73f1539d08..29f02d8513f6 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -956,6 +956,7 @@ struct page *vmalloc_to_page(void *addr); unsigned long vmalloc_to_pfn(void *addr); int remap_pfn_range(struct vm_area_struct *, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t); +int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *); struct page *follow_page(struct vm_area_struct *, unsigned long address, unsigned int foll_flags); diff --git a/mm/memory.c b/mm/memory.c index 8d10b5540c73..4b4fc3a7ea48 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1172,7 +1172,7 @@ static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *pa spinlock_t *ptl; retval = -EINVAL; - if (PageAnon(page) || !PageReserved(page)) + if (PageAnon(page)) goto out; retval = -ENOMEM; flush_dcache_page(page); @@ -1196,6 +1196,35 @@ out: return retval; } +/* + * This allows drivers to insert individual pages they've allocated + * into a user vma. + * + * The page has to be a nice clean _individual_ kernel allocation. + * If you allocate a compound page, you need to have marked it as + * such (__GFP_COMP), or manually just split the page up yourself + * (which is mainly an issue of doing "set_page_count(page, 1)" for + * each sub-page, and then freeing them one by one when you free + * them rather than freeing it as a compound page). + * + * NOTE! Traditionally this was done with "remap_pfn_range()" which + * took an arbitrary page protection parameter. This doesn't allow + * that. Your vma protection will have to be set up correctly, which + * means that if you want a shared writable mapping, you'd better + * ask for a shared writable mapping! + * + * The page does not need to be reserved. + */ +int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *page) +{ + if (addr < vma->vm_start || addr >= vma->vm_end) + return -EFAULT; + if (!page_count(page)) + return -EINVAL; + return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); +} +EXPORT_SYMBOL_GPL(vm_insert_page); + /* * Somebody does a pfn remapping that doesn't actually work as a vma. * @@ -1225,8 +1254,11 @@ static int incomplete_pfn_remap(struct vm_area_struct *vma, if (!pfn_valid(pfn)) return -EINVAL; - retval = 0; page = pfn_to_page(pfn); + if (!PageReserved(page)) + return -EINVAL; + + retval = 0; while (start < end) { retval = insert_page(vma->vm_mm, start, page, prot); if (retval < 0) -- cgit v1.2.3 From 346f7dbb17cb7d84317b4410df2e8f7bf2e57f44 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 30 Nov 2005 10:22:30 -0800 Subject: Revert "[PATCH] pci_ids.h: remove duplicate entries" This reverts commit c9d6073fb3cda856132dd544d537679f9715436c. It was totally bogus. Signed-off-by: Linus Torvalds --- include/linux/pci_ids.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 53e3293051d4..1e737e269db9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -387,6 +387,7 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 +#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 @@ -488,6 +489,8 @@ #define PCI_DEVICE_ID_AMD_8151_0 0x7454 #define PCI_DEVICE_ID_AMD_8131_APIC 0x7450 +#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A + #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 -- cgit v1.2.3