From jlan@sgi.com Fri Nov 2 11:59:21 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 02 Nov 2007 11:59:28 -0700 (PDT) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA2IxKBl019154 for ; Fri, 2 Nov 2007 11:59:21 -0700 Received: from [134.15.0.136] (mtv-vpn-sw-corp-0-136.corp.sgi.com [134.15.0.136]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lA2IxLke001308; Fri, 2 Nov 2007 11:59:22 -0700 Message-ID: <472B72B5.7020903@sgi.com> Date: Fri, 02 Nov 2007 11:55:49 -0700 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: Konstantin Baydarov CC: kdb@oss.sgi.com, Aaron Young Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI References: <20071008210936.7eba734d@localhost.localdomain> In-Reply-To: <20071008210936.7eba734d@localhost.localdomain> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1267 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Hi Konstantin, Thanks for your patch. It is in my queue. In addition, there are other USB keyboard/mouse problems in current KDB code: 1) uhci and ohci keyboard would not work if connected through a USB 2.0 hub, 2) hotplug USB keyboard does not work correctly. Aaron Young is working to fix these problems and provide ehci support for KDB. Thanks, - jay Konstantin Baydarov wrote: > Patch adds support of USB keyboard attached to UHCI in KDB. > Whole UHCI irq handler(uhci_irq) is called > periodically by KDB poll code when irqs are disabled. > I've tested patch with em64t pentiumd. USB keyboard attached to UHCI > works OK except there is 1 issue: auto reply of pressed key doesn't > work, but I don't think that is a critical issue. > > Patch against 2.6.23-rc8. > > Signed-off-by: Konstantin Baydarov > > arch/i386/Kconfig.debug | 4 ++-- > drivers/char/keyboard.c | 11 +++++++++++ > drivers/usb/host/uhci-hcd.c | 36 ++++++++++++++++++++++++++++++++++++ > include/linux/kdb.h | 1 + > kdb/kdbmain.c | 1 + > 5 files changed, 51 insertions(+), 2 deletions(-) > > Index: linux-2.6.23-rc8/drivers/usb/host/uhci-hcd.c > =================================================================== > --- linux-2.6.23-rc8.orig/drivers/usb/host/uhci-hcd.c > +++ linux-2.6.23-rc8/drivers/usb/host/uhci-hcd.c > @@ -41,6 +41,10 @@ > #include > #include > > +#ifdef CONFIG_KDB_USB > +#include > +#endif > + > #include > #include > #include > @@ -427,9 +431,37 @@ static irqreturn_t uhci_irq(struct usb_h > spin_unlock_irqrestore(&uhci->lock, flags); > } > > +#ifdef CONFIG_KDB_USB > + if (kdb_kbd_delay_enter){ > + kdb_kbd_delay_enter = 0; > +#ifndef CONFIG_PREEMPT_HARDIRQS > + kdb(KDB_REASON_KEYBOARD, 0, get_irq_regs()); > +#else > + KDB_ENTER(); > +#endif > + } > +#endif > + > return IRQ_HANDLED; > } > > +#ifdef CONFIG_KDB_USB > +void > +uhci_kdb_poll (void * __uhci, struct urb *urb) > +{ > + /* > + * NOTE - we use the uhci_hcd from the urb rather than the > + * __uhci parameter (which is NULL anyway). This ensures > + * that we will process the proper controller for the urb. > + */ > + > + if (!urb) /* can happen if no keyboard attached */ > + return; > + > + uhci_irq(bus_to_hcd(urb->dev->bus)); > +} > +#endif /* CONFIG_KDB_USB */ > + > /* > * Store the current frame number in uhci->frame_number if the controller > * is runnning. Expand from 11 bits (of which we use only 10) to a > @@ -661,6 +693,10 @@ static int uhci_start(struct usb_hcd *hc > configure_hc(uhci); > uhci->is_initialized = 1; > start_rh(uhci); > +#ifdef CONFIG_KDB_USB > + kdb_usb_infos.poll_func = uhci_kdb_poll; > + kdb_usb_infos.uhci = NULL; /* not used */ > +#endif > return 0; > > /* > Index: linux-2.6.23-rc8/drivers/char/keyboard.c > =================================================================== > --- linux-2.6.23-rc8.orig/drivers/char/keyboard.c > +++ linux-2.6.23-rc8/drivers/char/keyboard.c > @@ -43,6 +43,7 @@ > #include > #ifdef CONFIG_KDB > #include > +void uhci_kdb_poll (void * __uhci, struct urb *urb); > #endif /* CONFIG_KDB */ > > extern void ctrl_alt_del(void); > @@ -1149,6 +1150,16 @@ static void kbd_keycode(unsigned int key > > #ifdef CONFIG_KDB > if (down && !rep && keycode == KEY_PAUSE && kdb_on == 1) { > +#ifdef CONFIG_KDB_USB > + /* Is this USB keyboard attached to UHCI ? */ > + if ((kdb_usb_infos.poll_func == uhci_kdb_poll) > + && kdb_usb_infos.urb) > + /* uhci_irq should be completed before kernel > + * enters KDB > + */ > + kdb_kbd_delay_enter = 1; > + else > +#endif > kdb(KDB_REASON_KEYBOARD, 0, get_irq_regs()); > return; > } > Index: linux-2.6.23-rc8/include/linux/kdb.h > =================================================================== > --- linux-2.6.23-rc8.orig/include/linux/kdb.h > +++ linux-2.6.23-rc8/include/linux/kdb.h > @@ -162,5 +162,6 @@ int kdb_process_cpu(const struct task_st > } > > extern const char kdb_serial_str[]; > +extern int kdb_kbd_delay_enter; > > #endif /* !_KDB_H */ > Index: linux-2.6.23-rc8/kdb/kdbmain.c > =================================================================== > --- linux-2.6.23-rc8.orig/kdb/kdbmain.c > +++ linux-2.6.23-rc8/kdb/kdbmain.c > @@ -53,6 +53,7 @@ > volatile int kdb_flags; > atomic_t kdb_event; > atomic_t kdb_8250; > +int kdb_kbd_delay_enter = 0; > > /* > * kdb_lock protects updates to kdb_initial_cpu. Used to > Index: linux-2.6.23-rc8/arch/i386/Kconfig.debug > =================================================================== > --- linux-2.6.23-rc8.orig/arch/i386/Kconfig.debug > +++ linux-2.6.23-rc8/arch/i386/Kconfig.debug > @@ -156,8 +156,8 @@ config KDB_CONTINUE_CATASTROPHIC > setting to 2. > > config KDB_USB > - bool "Support for USB Keyboard in KDB (OHCI only)" > - depends on KDB && USB_OHCI_HCD > + bool "Support for USB Keyboard in KDB (OHCI and UHCI only)" > + depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD) > help > If you want to use kdb from a OHCI USB keyboard then say Y here. If you > say N then kdb can only be used from a PC (AT) keyboard or a serial > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Fri Nov 2 12:14:04 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 02 Nov 2007 12:14:10 -0700 (PDT) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA2JE3GL020660 for ; Fri, 2 Nov 2007 12:14:04 -0700 Received: from [134.15.0.136] (mtv-vpn-sw-corp-0-136.corp.sgi.com [134.15.0.136]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lA2Ibwke031847; Fri, 2 Nov 2007 11:37:58 -0700 Message-ID: <472B6DB1.5080904@sgi.com> Date: Fri, 02 Nov 2007 11:34:25 -0700 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: jidong xiao CC: kdb@oss.sgi.com Subject: Re: Question on kdb_event References: <4104961b0710310358y58bc0e1bm797fe236c8feb409@mail.gmail.com> In-Reply-To: <4104961b0710310358y58bc0e1bm797fe236c8feb409@mail.gmail.com> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1268 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb jidong xiao wrote: > Hi,all > > Can anyone kindly explain the usage of kdb_event?Thank you very much! > I saw this varible is used only in two places, inside kdb_printf() and > kdb(), kdb_event is incremented and decremented. But I have no idea > why do we need to use it in these two circumstance. KDB modifies in this way: #ifdef CONFIG_KDB #include #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && !oops_in_progress && !atomic_read(&kdb_event)) #else /* !CONFIG_KDB */ #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && !oops_in_progress) #endif /* CONFIG_KDB */ The counter of kdb_event affects the value of WARN_CONSOLE_UNLOCKED(). Thanks, - jay > > Regards > Jason > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jidong.xiao@gmail.com Sun Nov 4 21:48:02 2007 Received: with ECARTIS (v1.0.0; list kdb); Sun, 04 Nov 2007 21:48:08 -0800 (PST) Received: from rv-out-0910.google.com (rv-out-0910.google.com [209.85.198.184]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA55m0CF011716 for ; Sun, 4 Nov 2007 21:48:02 -0800 Received: by rv-out-0910.google.com with SMTP id k20so1079640rvb for ; Sun, 04 Nov 2007 21:48:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=oGObvBh62PbDtd9jzyx0glPdin7S2P+2h2CJfHUCgQ4=; b=WjRIgMBtlnTkDugY2NTr9eheGuahep7k0e/4VQUTjM7GT4Tb02QOHgBSs9YQNLFhM/SIJ3j+b3YKDYmT5AcUm73L0BYZudzx9f4dRGIKxh/7bvkyYOQ9IxQJHDmT+0RmHG6wDWUo/EWVCBxF6qCxW65Or+dpjRePrlrMFuxETPw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=Nj6z6zmSa2RyPbJeRw2nLglentBc3a8UdMLnBfjzua9j/+VlUdZYgHByhFBce9IPJ6nbYEYWYYpwtGzIIFuEhzoh7J/5r+xI69ucYsPwNxA9ceXEO71jpHVhr4L+nk8Sc74X3zG6WF2cbNeUjqCZ1zD657hHso9sd67T7mYUz9s= Received: by 10.142.47.6 with SMTP id u6mr896189wfu.1194240110265; Sun, 04 Nov 2007 21:21:50 -0800 (PST) Received: by 10.142.162.16 with HTTP; Sun, 4 Nov 2007 21:21:50 -0800 (PST) Message-ID: <4104961b0711042121s9fa9054m496f33ad581a56a8@mail.gmail.com> Date: Mon, 5 Nov 2007 13:21:50 +0800 From: "jidong xiao" To: "Jay Lan" Subject: Re: Question on kdb_event Cc: kdb@oss.sgi.com In-Reply-To: <472B6DB1.5080904@sgi.com> MIME-Version: 1.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Disposition: inline References: <4104961b0710310358y58bc0e1bm797fe236c8feb409@mail.gmail.com> <472B6DB1.5080904@sgi.com> X-archive-position: 1269 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jidong.xiao@gmail.com Precedence: bulk X-list: kdb On Nov 3, 2007 2:34 AM, Jay Lan wrote: > > jidong xiao wrote: > > Hi,all > > > > Can anyone kindly explain the usage of kdb_event?Thank you very much! > > I saw this varible is used only in two places, inside kdb_printf() and > > kdb(), kdb_event is incremented and decremented. But I have no idea > > why do we need to use it in these two circumstance. > > KDB modifies in this way: > #ifdef CONFIG_KDB > #include > #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && > !oops_in_progress && !atomic_read(&kdb_event)) > #else /* !CONFIG_KDB */ > #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && > !oops_in_progress) > #endif /* CONFIG_KDB */ > > The counter of kdb_event affects the value of WARN_CONSOLE_UNLOCKED(). > > Thanks, > - jay > Well yes I saw kdb modifies WARN_CONSOLE_UNLOCKED, and I can understand the reason that kdb_event is incremented/decremented in kdb_printf(), because kdb_printf() will finally invoke vt_console_print()->hide_cursor()->clear_selection()->highlight_pointer()->complement_pos(), inside complement_pos(), WARN_CONSOLE_UNLOCKED is called. so in kdb_printf() we should increment kdb_event to avoid the warning message,or in other words, to avoid deadlock. But what I can't understand is that why we increment kdb_event at the begining of kdb()?Is it neccessary? Thanks Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Mon Nov 5 08:39:08 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 05 Nov 2007 08:39:15 -0800 (PST) Received: from buildserver.ru.mvista.com (rtsoft3.corbina.net [85.21.88.6] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA5Gd46V024890 for ; Mon, 5 Nov 2007 08:39:07 -0800 Received: from medved (unknown [10.150.0.9]) by buildserver.ru.mvista.com (Postfix) with ESMTP id AF45C8810; Mon, 5 Nov 2007 20:39:07 +0400 (SAMT) Date: Mon, 5 Nov 2007 19:39:11 +0300 From: Konstantin Baydarov To: Jay Lan Cc: kdb@oss.sgi.com, Aaron Young Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071105193911.303cc50b@medved> In-Reply-To: <472B72B5.7020903@sgi.com> References: <20071008210936.7eba734d@localhost.localdomain> <472B72B5.7020903@sgi.com> X-Mailer: Claws Mail 2.9.1 (GTK+ 2.10.4; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1270 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Fri, 02 Nov 2007 11:55:49 -0700 Jay Lan wrote: > Hi Konstantin, > > Thanks for your patch. It is in my queue. > > In addition, there are other USB keyboard/mouse problems in > current KDB code: > 1) uhci and ohci keyboard would not work if connected through > a USB 2.0 hub, > 2) hotplug USB keyboard does not work correctly. > > Aaron Young is working to fix these problems and provide > ehci support for KDB. > > Thanks, > - jay > > Hi Jay. You mean external 2.0 hub? I've attached keyboard to the EHCI port of PC - I believe it works ok. AFAIK EHCI manages high speed devices and it emulates OHCI or UHCI for low speed devices like keyboard, so It should work with EHCI. This is the new version of UHCI support in KDB. Because previous version is unsafe. Previous fix issues: - When CPU1 executes uhci_irq(), UHCI locks are acquired. If in the same time KDB bp occurs on CPU2, KDB stops kernel and tries to acquire the same UHCI spinlock in uhci_irq() called by KDB. That results in deadlock, because KDB will never enable IRQ before it completes. - Even if CPU1 executes uhci_irq() and lock is released KDB can't be started untill uhci_irq() is finished, because uhci_irq() is not reentrant function and probably UHCI scheduler can be broken by KDB. - KDB code should manage only HID Keyboard URB. It can't be done if KDB uses whole uhci_irq() handler. Because uhci_irq manages Queue Heads(QH), not URBs, and in QH that contain KDB URB can be other URBs. KDB UHCI poll driver requiremens based on issues: - driver should not require any of UCHI kernel spinlocks. - driver shouldn't require sync with kernel UHCI driver. - driver should work with hardware UHCI scheduler and don't touch software scheduler, because without sync with kernel driver sw scheduler can be broken by KDB. - driver should manage only KDB URB. As HW ans SW schedulers of UHCI works with QH, not with URBs, special KDB QH should be allocated and KDB URB shuld be added to this QH. KDB QH should contain only KDB urb. Necessary changes of kernel UHCI driver: - KDB QH and URB should not be managed. Current version of KDB poll driver manages HW UHCI scheduler so it can be executed even if kernel UHCI driver is stopped. Main concepts KDB drivers: - Allocation of KDB QH and KDB URB Allocation of KDB URB occurs in HID driver, because only there we know if keyboard is attached (see kdb_uhci_submit_urb()). HID core uses Interrupt URB(inurb) to get keyboard codes. After urbin was sent, KDB sends it's own interrupt urb with same parameters(DevAddr, Endpoint). While KDB URB is sent, the brand new KDB QH(kdb_uhci_hid_qh) is allocated and KDB URB transfer descriptors(TD) are linked into KDB QH. KDB QH and KDB URB will never be managed by kernel driver so KDB QH will always be in hardware scheduler of UHCI. When kernel enters KDB we just need to reactivate KDB QH periodically without change software scheduler of kernel driver and we don't need to free/allocate memory for KDB QH and URB because whose will never be freed/unlinked by kernel driver. - Reenabling of KDB QH KDB poll code periodically check if KDB QH was advanced(key was pressed) in uhci_check_kdb_uhci_qh(). To reenable KDB QH kdb_activate_uhci_qh() activate every TD linked in KDB QH except last one that is dummy. Then, to reenable KDB QH, pointer to first TD is written to element field of KDB QH. Changes of KDB USB code: - kdb_hcd_type was added, it determines if Keyboard is attached to OHCI or UCHI. Probably KDB should determine it without help of kdb_hcd_type. kdb_hcd_type can be set by kernel config or in kernel parameters(kdbohci/kdbuhci). - struct urb *hid_urbin was added to struct kdb_usb_exchange to recognize HID keyboard used by KDB. - void (*urb_complete)(void *, struct urb *) was added to struct kdb_usb_exchange. In UHCI case this callback is called from get_usb_char(), when KDB URB is processed, to reenable KDB QH. Known Issues of KDB driver: - Autoreply of pressed key doesn't work - When kernel enters KDB first pressed key doesn't appear on KDB console, because it's caught by UHCI kernel driver. - Keyboard hotplug wasn't tested. Patch is against 2.6.23-rc8. Signed-off-by: Konstantin Baydarov Index: linux-2.6.23-rc8/drivers/usb/host/uhci-q.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/usb/host/uhci-q.c +++ linux-2.6.23-rc8/drivers/usb/host/uhci-q.c @@ -25,6 +25,11 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +static struct uhci_qh *kdb_uhci_hid_qh; +#endif + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -292,6 +297,58 @@ static struct uhci_qh *uhci_alloc_qh(str return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1396,6 +1453,20 @@ static int uhci_urb_enqueue(struct usb_h if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (urb == kdb_usb_infos.urb && kdb_usb_infos.urb){ + /* KDB urb will be enqued only once */ + kdb_uhci_hid_qh = NULL; + qh = kdb_uhci_alloc_qh(uhci, urb->dev, hep); + if (!qh) + goto err_no_qh; + kdb_uhci_hid_qh = qh; + } else +#endif if (hep->hcpriv) qh = (struct uhci_qh *) hep->hcpriv; else { @@ -1657,6 +1728,13 @@ static int uhci_advance_check(struct uhc int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if (qh == kdb_uhci_hid_qh){ + ret = 0; + goto done; + } +#endif if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1749,6 +1827,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if (qh == kdb_uhci_hid_qh) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1775,3 +1858,78 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +static int kdb_hid_event = 0; /* eq 1 when key was pressed/released */ + +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(void) +{ + struct urb_priv *urbp; + struct uhci_td *td; + struct uhci_qh *qh = kdb_uhci_hid_qh; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (void * __uhci, struct urb *urb) +{ + + if (!kdb_hid_event) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(); + kdb_hid_event = 0; +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static void uhci_check_kdb_uhci_qh(void) +{ + struct uhci_qh *qh = kdb_uhci_hid_qh; + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)) + /* We're okay, the queue has advanced */ + kdb_hid_event = 1; +} +#endif Index: linux-2.6.23-rc8/drivers/hid/usbhid/hid-core.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/hid/usbhid/hid-core.c +++ linux-2.6.23-rc8/drivers/hid/usbhid/hid-core.c @@ -45,6 +45,23 @@ #ifdef CONFIG_KDB_USB #include + +#if defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE) +struct urbin_saved_data { + /* Needed to fill KDB in URB */ + struct usb_device *uhci_dev; + int uhci_pipe; + int uhci_insize; + int uhci_interval; + dma_addr_t uhci_inbuf_dma; +}; + +static struct urbin_saved_data kdb_urbin_param = + {0, 0, 0, 0, 0}; + +static int kdb_uhci_hid_initialized = 0; +#endif + #endif static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", @@ -796,6 +813,20 @@ static struct hid_device *usb_hid_config hid_irq_in, hid, interval); usbhid->urbin->transfer_dma = usbhid->inbuf_dma; usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + +#if (defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE)) && \ + defined(CONFIG_KDB_USB) + /* Save urbin parameters */ + if (!kdb_uhci_hid_initialized && + kdb_hcd_type == KDB_HCD_UHCI){ + kdb_usb_infos.hid_urbin = usbhid->urbin; + kdb_urbin_param.uhci_dev = dev; + kdb_urbin_param.uhci_pipe = pipe; + kdb_urbin_param.uhci_insize = insize; + kdb_urbin_param.uhci_interval = interval; + } +#endif + } else { if (usbhid->urbout) continue; @@ -901,8 +932,24 @@ static void hid_disconnect(struct usb_in #ifdef CONFIG_KDB_USB /* Unlink the KDB USB struct */ - if (usbhid->urbin == kdb_usb_infos.urb) - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); + if (usbhid->urbin == kdb_usb_infos.urb){ +#if defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE) + if (kdb_uhci_hid_initialized && kdb_hcd_type == KDB_HCD_UHCI){ + kdb_uhci_hid_initialized = 0; + /* Cleanup */ + if (kdb_usb_infos.buffer) + usb_buffer_free(kdb_urbin_param.uhci_dev, + usbhid->bufsize, kdb_usb_infos.buffer, + kdb_urbin_param.uhci_inbuf_dma); + + if (kdb_usb_infos.urb) + usb_free_urb(kdb_usb_infos.urb); + } +#endif + kdb_usb_infos.urb = NULL; + kdb_usb_infos.buffer = NULL; + kdb_usb_infos.hid_urbin = NULL; + } #endif spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ @@ -929,6 +976,60 @@ static void hid_disconnect(struct usb_in hid_free_device(hid); } +#if (defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE)) && \ + defined(CONFIG_KDB_USB) +static void kdb_uhci_submit_urb(struct usbhid_device * usbhid) +{ + if (kdb_usb_infos.hid_urbin != usbhid->urbin || + !kdb_usb_infos.hid_urbin || kdb_uhci_hid_initialized) + return; + + kdb_uhci_hid_initialized = 0; + if (!(kdb_usb_infos.buffer = + usb_buffer_alloc(kdb_urbin_param.uhci_dev, + usbhid->bufsize, GFP_ATOMIC, + &kdb_urbin_param.uhci_inbuf_dma))) + goto out; + + if (!(kdb_usb_infos.urb = + usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + usb_fill_int_urb(kdb_usb_infos.urb, + kdb_urbin_param.uhci_dev, + kdb_urbin_param.uhci_pipe, + kdb_usb_infos.buffer, + kdb_urbin_param.uhci_insize, + hid_irq_in, + usbhid, + kdb_urbin_param.uhci_interval); + + (kdb_usb_infos.urb)->transfer_dma = kdb_urbin_param.uhci_inbuf_dma; + (kdb_usb_infos.urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + if (usb_submit_urb(kdb_usb_infos.urb, GFP_ATOMIC)) + goto out; + + kdb_uhci_hid_initialized = 1; +out: + if (kdb_uhci_hid_initialized) + return; + + /* Some Error Cleanup */ + printk("\n\t\t KDB: Error, UHCI Keyboard HID won't work!"); + if (kdb_usb_infos.buffer) + usb_buffer_free(kdb_urbin_param.uhci_dev, + usbhid->bufsize, kdb_usb_infos.buffer, + kdb_urbin_param.uhci_inbuf_dma); + + if (kdb_usb_infos.urb) + usb_free_urb(kdb_usb_infos.urb); + + kdb_usb_infos.buffer = NULL; + kdb_usb_infos.urb = NULL; +} +#endif + static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct hid_device *hid; @@ -995,8 +1096,18 @@ static int hid_probe(struct usb_interfac /* Initialization of the KDB structure */ if (!strcmp(c, "Keyboard")) { struct usbhid_device *usbhid = hid->driver_data; - kdb_usb_infos.urb = usbhid->urbin; - kdb_usb_infos.buffer = usbhid->inbuf; + +#if defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE) + if (kdb_hcd_type == KDB_HCD_UHCI){ + kdb_uhci_submit_urb(usbhid); + } +#endif +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + if (kdb_hcd_type == KDB_HCD_OHCI){ + kdb_usb_infos.urb = usbhid->urbin; + kdb_usb_infos.buffer = usbhid->inbuf; + } +#endif kdb_usb_infos.reset_timer = NULL; } #endif Index: linux-2.6.23-rc8/include/linux/kdb.h =================================================================== --- linux-2.6.23-rc8.orig/include/linux/kdb.h +++ linux-2.6.23-rc8/include/linux/kdb.h @@ -142,11 +142,18 @@ extern void smp_kdb_stop(void); #ifdef CONFIG_KDB_USB #include +#define KDB_HCD_OHCI 0 +#define KDB_HCD_UHCI 1 + +extern int kdb_hcd_type; + struct kdb_usb_exchange { void *uhci; /* pointer to the UHCI structure */ struct urb *urb; /* pointer to the URB */ unsigned char *buffer; /* pointer to buffer */ + struct urb *hid_urbin; /* pointer to HID URB */ void (*poll_func)(void *, struct urb *); /* pointer to the polling function */ + void (*urb_complete)(void *, struct urb *); /* pointer to the complete function */ void (*reset_timer)(void); /* pointer to the reset timer function */ }; extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */ @@ -162,5 +169,6 @@ int kdb_process_cpu(const struct task_st } extern const char kdb_serial_str[]; +extern int kdb_kbd_delay_enter; #endif /* !_KDB_H */ Index: linux-2.6.23-rc8/drivers/usb/host/uhci-hcd.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/usb/host/uhci-hcd.c +++ linux-2.6.23-rc8/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,10 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include +#endif + /* * Version Information */ @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +static void +uhci_kdb_poll (void * __uhci, struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return; + + uhci_check_kdb_uhci_qh(); +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -661,6 +676,15 @@ static int uhci_start(struct usb_hcd *hc configure_hc(uhci); uhci->is_initialized = 1; start_rh(uhci); + +#ifdef CONFIG_KDB_USB + if (kdb_hcd_type == KDB_HCD_UHCI){ + kdb_usb_infos.poll_func = uhci_kdb_poll; + kdb_usb_infos.uhci = NULL; /* not used */ + kdb_usb_infos.urb_complete = kdb_uhci_urb_complete; + } +#endif + return 0; /* Index: linux-2.6.23-rc8/arch/i386/kdb/kdba_io.c =================================================================== --- linux-2.6.23-rc8.orig/arch/i386/kdb/kdba_io.c +++ linux-2.6.23-rc8/arch/i386/kdb/kdba_io.c @@ -61,22 +61,27 @@ static int get_usb_char(void) static int usb_lock; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int ret, i, max; + ret = -1; /* Is USB initialized ? */ if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) - return -1; + return ret; /* Transfer char if they are present */ (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); + for (i=0; i<4; i++){ + if (!kdb_usb_infos.buffer[2+i]) + break; + } + max = i + 1; + spec = kdb_usb_infos.buffer[0]; - keycode = kdb_usb_infos.buffer[2]; + keycode = kdb_usb_infos.buffer[max]; kdb_usb_infos.buffer[0] = (char)0; kdb_usb_infos.buffer[2] = (char)0; - if(kdb_usb_infos.buffer[3]) - return -1; - /* A normal key is pressed, decode it */ if(keycode) keycode = kdb_usb_keycode[keycode]; @@ -87,10 +92,12 @@ static int get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -101,28 +108,43 @@ static int get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; + ret = 13; + break; case 0x3A: /* Capslock */ usb_lock ? (usb_lock = 0) : (usb_lock = 1); break; case 0x0E: /* Backspace */ - return 8; + ret = 8; + break; case 0x0F: /* TAB */ - return 9; + ret = 9; + break; case 0x77: /* Pause */ - break ; + ret = -1; + break; default: if(!usb_lock) { - return plain_map[keycode]; + ret = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret = shift_map[keycode]; + break; } } } } - return -1; + + for(i=0; i<8; i++){ + kdb_usb_infos.buffer[i] = (char)0; + } + + if (kdb_usb_infos.urb_complete){ + (*kdb_usb_infos.urb_complete)(kdb_usb_infos.uhci, + (struct urb *)kdb_usb_infos.urb); + } + return ret; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.23-rc8/arch/i386/Kconfig.debug =================================================================== --- linux-2.6.23-rc8.orig/arch/i386/Kconfig.debug +++ linux-2.6.23-rc8/arch/i386/Kconfig.debug @@ -156,11 +156,26 @@ config KDB_CONTINUE_CATASTROPHIC setting to 2. config KDB_USB - bool "Support for USB Keyboard in KDB (OHCI only)" - depends on KDB && USB_OHCI_HCD + bool "Support for USB Keyboard in KDB" + depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD) help - If you want to use kdb from a OHCI USB keyboard then say Y here. If you + If you want to use kdb from a USB keyboard then say Y here. If you say N then kdb can only be used from a PC (AT) keyboard or a serial console. +choice + prompt "Keyboard HCD Type" + default KDB_UHCI + depends on KDB_USB + +config KDB_USB_UHCI + bool "Keyboard is attached to UHCI" + depends on USB_UHCI_HCD + +config KDB_USB_OHCI + bool "Keyboard is attached to OHCI" + depends on USB_OHCI_HCD + +endchoice + endmenu Index: linux-2.6.23-rc8/drivers/usb/host/ohci-pci.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/usb/host/ohci-pci.c +++ linux-2.6.23-rc8/drivers/usb/host/ohci-pci.c @@ -220,7 +220,7 @@ static int __devinit ohci_pci_start (str ohci_stop (hcd); } #ifdef CONFIG_KDB_USB - if (ret >= 0) { + if (ret >= 0 && kdb_hcd_type == KDB_HCD_OHCI) { kdb_usb_infos.poll_func = ohci_kdb_poll; kdb_usb_infos.uhci = NULL; /* not used */ } Index: linux-2.6.23-rc8/kdb/kdb_io.c =================================================================== --- linux-2.6.23-rc8.orig/kdb/kdb_io.c +++ linux-2.6.23-rc8/kdb/kdb_io.c @@ -656,7 +656,43 @@ kdb_io_init(void) if (!vt_console) KDB_FLAG_SET(NO_VT_CONSOLE); kdb_input_flush(); + +#ifdef CONFIG_KDB_USB + if (kdb_hcd_type == -1){ +#ifdef CONFIG_KDB_USB_OHCI + kdb_hcd_type = KDB_HCD_OHCI; +#endif + +#ifdef CONFIG_KDB_USB_UHCI + kdb_hcd_type = KDB_HCD_UHCI; +#endif + } +#endif + return; } +#ifdef CONFIG_KDB_USB +int kdb_hcd_type = -1; /* undefined */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static int __init opt_kdbohci(char *str) +{ + kdb_hcd_type = KDB_HCD_OHCI; + return 0; +} + +early_param("kdbohci", opt_kdbohci); +#endif +#if defined(CONFIG_USB_UHCI_HCD) || defined(CONFIG_USB_UHCI_HCD_MODULE) +static int __init opt_kdbuhci(char *str) +{ + kdb_hcd_type = KDB_HCD_UHCI; + return 0; +} + +early_param("kdbuhci", opt_kdbuhci); +#endif +#endif + EXPORT_SYMBOL(kdb_read); --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Mon Nov 5 10:17:09 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 05 Nov 2007 10:17:14 -0800 (PST) Received: from buildserver.ru.mvista.com (rtsoft3.corbina.net [85.21.88.6] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA5IH7XD008923 for ; Mon, 5 Nov 2007 10:17:08 -0800 Received: from medved (unknown [10.150.0.9]) by buildserver.ru.mvista.com (Postfix) with ESMTP id 8BB7F8810; Mon, 5 Nov 2007 22:17:11 +0400 (SAMT) Date: Mon, 5 Nov 2007 21:17:16 +0300 From: Konstantin Baydarov To: Aaron Young Cc: jlan@sgi.com (Jay Lan), kdb@oss.sgi.com, ayoung@cthulhu.engr.sgi.com (Aaron Young) Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071105211716.14674612@medved> In-Reply-To: <200711051724.lA5HOHMV4005128@kluge.engr.sgi.com> References: <20071105193911.303cc50b@medved> <200711051724.lA5HOHMV4005128@kluge.engr.sgi.com> X-Mailer: Claws Mail 2.9.1 (GTK+ 2.10.4; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1271 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Mon, 5 Nov 2007 09:24:17 -0800 (PST) Aaron Young wrote: > If a USB keyboard (a "low" speed device) is connected directly to > a EHCI port, the "companion" controller (i.e. uhci_hcd or ohc_hcd > driver) will take control of it (and work fine in kdb). However, if > the keyboard is connected through a USB2.0 > hub, the ehci_hcd driver will take control of it. Therefore, the > problem is that kdb will call a ohci or uhci driver "poll" function > when the ehci driver is managing the keyboard. This causes kdb itself > to crash on ohci/ehci based controllers... not sure about uhci, but > it doesn't seem like it would work right. > > I am working on a fix for this problem and also to provide support > for multiple USB keyboards - since right now kdb only makes use of > a single USB keyboard. It would be better if kdb would "multiplex" > the input of all connected USB keyboards. > > So, if any of your code below makes any of the assumptions I mention > above (such as there is only one kdb USB keyboard used for input or > the keyboard is using either the ohci_hcd or uhci_hcd driver and > not ehci_hcd), it will have to be changed/incorporated to work with > my new code... > > I hope to have this new code within a couple of weeks... > > -Aaron Young > Yes my code makes assumption that there is only one Kbd and it's attached to OHCI/UHCI so definitely should be changed/incorporated. Aaron, what about UHCI part of code, can you review this? --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Wed Nov 7 06:12:11 2007 Received: with ECARTIS (v1.0.0; list kdb); Wed, 07 Nov 2007 06:12:17 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lA7EC8jr004107 for ; Wed, 7 Nov 2007 06:12:10 -0800 Received: (qmail 8835 invoked from network); 7 Nov 2007 14:12:12 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.130) by mail.dev.rtsoft.ru with SMTP; 7 Nov 2007 14:12:12 -0000 Date: Wed, 7 Nov 2007 17:11:37 +0300 From: Konstantin Baydarov To: Aaron Young Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071107171137.792d0304@localhost.localdomain> In-Reply-To: <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1272 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Mon, 5 Nov 2007 10:54:42 -0800 (PST) Aaron Young wrote: > I've only dealt with OHCI driver code before, so I'm not qualified > to review the UHCI specific code for you. As you say, it looks like a > lot of your infastructure code introduces new globals (kdb_hcd_type) > and uses kdb_usb_infos a lot - which is going away with my new > implementation. > > Would it be possible for you to wait for my new kdb/usb > infastructure code and re-implement your UHCI code against it at that > time? I could attempt to take an in depth look at it at that time > perhaps... > > Thanks, > > -Aaron Yes I'll intergrate UCHI code to the new KDB. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 9 13:38:58 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 09 Nov 2007 13:39:06 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA9Lcvh8002593 for ; Fri, 9 Nov 2007 13:38:58 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lA9LdCK95151090 for ; Fri, 9 Nov 2007 13:39:12 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lA9LdBwF5074249 for kdb@oss.sgi.com; Fri, 9 Nov 2007 13:39:11 -0800 (PST) Date: Fri, 9 Nov 2007 13:39:11 -0800 (PST) From: Aaron Young Message-Id: <200711092139.lA9LdBwF5074249@kluge.engr.sgi.com> To: kdb@oss.sgi.com Subject: [PATCH] New USB Keyboard interface for KDB X-archive-position: 1273 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb This patch implements a new KDB interface for USB keyboards which fixes the following problems: 1. Currently KDB is only "OHCI" type USB aware. If a keyboard is attached via a USB2.0 hub, the Linux kernel EHCI driver is used instead of OHCI, but kdb will still attempt to use the OHCI driver poll interface to read a character from the keyboard - this results in a crash from within kdb and, hence, kdb is unuseable. This patch allows KDB to work with any Host Contoller driver and call the correct HC driver poll routine (as long as the HC driver provides a .kdb_poll_char routine via it's associated hc_driver struct). If a HC driver is managing a keyboard, but doesn't provide a valid .kdb_poll_char routine, the keyboard will be ignored by KDB. 2. Hotplug - currently, if a USB keyboard is unplugged and plugged back in, KDB loses track and no longer recognizes the keyboard for use from KDB. This is because the "kdb_usb_infos" struct was getting zeroed and the .poll_func field set to NULL on hotunplugs (and not set to something valid on hotplugs) Hotplugged keyboards are now recognized by KDB. 3. Currently KDB can only make use of 1 USB type keyboard. This is because of the single "kdb_usb_infos" structure interface - which can only describe a single keyboard/urb. New code can handle up to 8 attached keyboards - input is multiplexed from all of them while in kdb. The number of supported USB keyboards can easily be changed via the KDB_USB_NUM_KEYBOARDS def in appropriate arch/XXX/kdb//kdba_io.c file. General notes about the new code: The new USB interface is composed of two new routines which HID drivers need to call when configuring USB keyboards: kdb_usb_keyboard_attach() - to attach a USB keyboard to KDB kdb_usb_keyboard_detach() - to detach a USB keyboard from KDB These should be called from the hotplug interfaces so that hotplugs/ unplugs keep KDB up-to-date on what keyboards are on the system. Each USB Host Controller driver which could manage keyboards needs to add a .kdb_poll_char entry to it's associated hc_driver struct and and, of course, provide the routine to poll a keyboard's URB for characters. The OHCI implementation is complete and there. UHCI is completely missing at this point and EHCI is partially there - i.e. EHCI provides the .kdb_poll_char entry, but the associated routine, ehci_kdb_poll_char() is not yet implemented (and just returns -1 for now). I plan to work on the EHCI poll code next. I hope to have a subsequent patch for this very soon. Issues: While testing I noticed some issues when using hubs to attach USB keyboards. When multiple keyboards are attached via a USB1.1 hub, only one of the keyboards is operational from kdb - not sure why. It's probably a shortcoming of the OHCI poll character code. Also, it appears hotplug of USB1.1 hubs doesn't work right in Linux and the HID hotplug interfaces are not called for the attached keyboards. Hotplug does work correctly with USB2.0 hubs however. When keyboard(s) are attached directly to USB ports (with no hubs), I could find no issues - hotplug/unplug, mulitplexing all appear to work properly. Testing: These changes have only been tested on a ia64 machine containing OHCI/EHCI style USB controllers. Additional testing on other archs and USB configs by others would be appreciated. Patch is against 2.6.23-rc8 (should be applied after kdb-4.4-2.6.23-*.1 patch set) Signed-off-by: Aaron Young (ayoung@sgi.com) --- diff -pNaru linux.orig/arch/i386/kdb/kdba_io.c linux/arch/i386/kdb/kdba_io.c --- linux.orig/arch/i386/kdb/kdba_io.c 2007-11-09 11:37:45.000000000 -0800 +++ linux/arch/i386/kdb/kdba_io.c 2007-11-08 14:26:07.710994431 -0800 @@ -29,9 +29,10 @@ #endif #ifdef CONFIG_KDB_USB -struct kdb_usb_exchange kdb_usb_infos; -EXPORT_SYMBOL(kdb_usb_infos); +/* support up to 8 USB keyboards (probably excessive, but...) */ +#define KDB_USB_NUM_KEYBOARDS 8 +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; -/* get_usb_char - * This function drives the UHCI controller, - * fetch the USB scancode and decode it +/* + * kdb_usb_keyboard_attach() + * Attach a USB keyboard to kdb. */ -static int get_usb_char(void) +int +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) { - static int usb_lock; - unsigned char keycode, spec; - extern u_short plain_map[], shift_map[], ctrl_map[]; + int i; + int rc = -1; - /* Is USB initialized ? */ - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) - return -1; + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for a free index. If found, assign the keyboard to + * the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb) /* index is already assigned */ + continue; + + /* found a free array index */ + kdb_usb_kbds[i].urb = urb; + kdb_usb_kbds[i].buffer = buffer; + kdb_usb_kbds[i].poll_func = poll_func; - /* Transfer char if they are present */ - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); + rc = 0; /* success */ - spec = kdb_usb_infos.buffer[0]; - keycode = kdb_usb_infos.buffer[2]; - kdb_usb_infos.buffer[0] = (char)0; - kdb_usb_infos.buffer[2] = (char)0; + break; + } - if(kdb_usb_infos.buffer[3]) - return -1; + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); - /* A normal key is pressed, decode it */ - if(keycode) - keycode = kdb_usb_keycode[keycode]; - - /* 2 Keys pressed at one time ? */ - if (spec && keycode) { - switch(spec) - { - case 0x2: - case 0x20: /* Shift */ - return shift_map[keycode]; - case 0x1: - case 0x10: /* Ctrl */ - return ctrl_map[keycode]; - case 0x4: - case 0x40: /* Alt */ - break; - } - } - else { - if(keycode) { /* If only one key pressed */ - switch(keycode) - { - case 0x1C: /* Enter */ - return 13; - - case 0x3A: /* Capslock */ - usb_lock ? (usb_lock = 0) : (usb_lock = 1); - break; - case 0x0E: /* Backspace */ - return 8; - case 0x0F: /* TAB */ - return 9; - case 0x77: /* Pause */ - break ; - default: - if(!usb_lock) { - return plain_map[keycode]; - } - else { - return shift_map[keycode]; - } - } - } - } - return -1; +/* + * kdb_usb_keyboard_detach() + * Detach a USB keyboard from kdb. + */ +int +kdb_usb_keyboard_detach(struct urb *urb) +{ + int i; + int rc = -1; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for the index with the matching URB. If found, + * clear the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb != urb) + continue; + + /* found it, clear the index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].caps_lock = 0; + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); + +/* + * get_usb_char + * This function drives the USB attached keyboards. + * Fetch the USB scancode and decode it. + */ +static int +get_usb_char(void) +{ + int i; + int ret; + unsigned char keycode, spec; + extern u_short plain_map[], shift_map[], ctrl_map[]; + + /* + * Loop through all the USB keyboard(s) and return + * the first character obtained from them. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + /* skip uninitialized keyboard array entries */ + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || + !kdb_usb_kbds[i].poll_func) + continue; + + /* Transfer char */ + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (ret == -1) /* error or no characters, try the next kbd */ + continue; + + spec = kdb_usb_kbds[i].buffer[0]; + keycode = kdb_usb_kbds[i].buffer[2]; + kdb_usb_kbds[i].buffer[0] = (char)0; + kdb_usb_kbds[i].buffer[2] = (char)0; + + if(kdb_usb_kbds[i].buffer[3]) { + kdb_usb_kbds[i].buffer[3] = (char)0; + continue; + } + + /* A normal key is pressed, decode it */ + if(keycode) + keycode = kdb_usb_keycode[keycode]; + + /* 2 Keys pressed at one time ? */ + if (spec && keycode) { + switch(spec) + { + case 0x2: + case 0x20: /* Shift */ + return shift_map[keycode]; + case 0x1: + case 0x10: /* Ctrl */ + return ctrl_map[keycode]; + case 0x4: + case 0x40: /* Alt */ + break; + } + } else if (keycode) { /* If only one key pressed */ + switch(keycode) + { + case 0x1C: /* Enter */ + return 13; + + case 0x3A: /* Capslock */ + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); + break; + case 0x0E: /* Backspace */ + return 8; + case 0x0F: /* TAB */ + return 9; + case 0x77: /* Pause */ + break ; + default: + if(!kdb_usb_kbds[i].caps_lock) { + return plain_map[keycode]; + } + else { + return shift_map[keycode]; + } + } + } + } + + /* no chars were returned from any of the USB keyboards */ + + return -1; } #endif /* CONFIG_KDB_USB */ diff -pNaru linux.orig/arch/ia64/kdb/kdba_io.c linux/arch/ia64/kdb/kdba_io.c --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-09 11:37:47.000000000 -0800 +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-08 14:31:06.500022083 -0800 @@ -39,9 +39,10 @@ #endif #ifdef CONFIG_KDB_USB -struct kdb_usb_exchange kdb_usb_infos; -EXPORT_SYMBOL(kdb_usb_infos); +/* support up to 8 USB keyboards (probably excessive, but...) */ +#define KDB_USB_NUM_KEYBOARDS 8 +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, @@ -62,39 +63,122 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; -/* get_usb_char - * This function drives the UHCI controller, - * fetch the USB scancode and decode it +/* + * kdb_usb_keyboard_attach() + * Attach a USB keyboard to kdb. */ -static int get_usb_char(void) +int +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) { - static int usb_lock; - unsigned char keycode, spec; - extern u_short plain_map[], shift_map[], ctrl_map[]; + int i; + int rc = -1; - /* Is USB initialized ? */ - if (!kdb_usb_infos.poll_func || !kdb_usb_infos.urb || !kdb_usb_infos.buffer) - return -1; + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for a free index. If found, assign the keyboard to + * the array index. + */ - /* Transfer char if they are present */ - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb) /* index is already assigned */ + continue; + + /* found a free array index */ + kdb_usb_kbds[i].urb = urb; + kdb_usb_kbds[i].buffer = buffer; + kdb_usb_kbds[i].poll_func = poll_func; - spec = kdb_usb_infos.buffer[0]; - keycode = kdb_usb_infos.buffer[2]; - kdb_usb_infos.buffer[0] = (char)0; - kdb_usb_infos.buffer[2] = (char)0; + rc = 0; /* success */ - if(kdb_usb_infos.buffer[3]) - return -1; + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); + +/* + * kdb_usb_keyboard_detach() + * Detach a USB keyboard from kdb. + */ +int +kdb_usb_keyboard_detach(struct urb *urb) +{ + int i; + int rc = -1; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for the index with the matching URB. If found, + * clear the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb != urb) + continue; + + /* found it, clear the index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].caps_lock = 0; + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); + +/* + * get_usb_char + * This function drives the USB attached keyboards. + * Fetch the USB scancode and decode it. + */ +static int +get_usb_char(void) +{ + int i; + int ret; + unsigned char keycode, spec; + extern u_short plain_map[], shift_map[], ctrl_map[]; + + /* + * Loop through all the USB keyboard(s) and return + * the first character obtained from them. + */ - /* A normal key is pressed, decode it */ - if(keycode) - keycode = kdb_usb_keycode[keycode]; + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + /* skip uninitialized keyboard array entries */ + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || + !kdb_usb_kbds[i].poll_func) + continue; + + /* Transfer char */ + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (ret == -1) /* error or no characters, try the next kbd */ + continue; + + spec = kdb_usb_kbds[i].buffer[0]; + keycode = kdb_usb_kbds[i].buffer[2]; + kdb_usb_kbds[i].buffer[0] = (char)0; + kdb_usb_kbds[i].buffer[2] = (char)0; + + if(kdb_usb_kbds[i].buffer[3]) { + kdb_usb_kbds[i].buffer[3] = (char)0; + continue; + } - /* 2 Keys pressed at one time ? */ - if (spec && keycode) { - switch(spec) - { + /* A normal key is pressed, decode it */ + if(keycode) + keycode = kdb_usb_keycode[keycode]; + + /* 2 Keys pressed at one time ? */ + if (spec && keycode) { + switch(spec) + { case 0x2: case 0x20: /* Shift */ return shift_map[keycode]; @@ -104,34 +188,35 @@ static int get_usb_char(void) case 0x4: case 0x40: /* Alt */ break; - } - } - else { - if(keycode) { /* If only one key pressed */ + } + } else if (keycode) { /* If only one key pressed */ switch(keycode) { - case 0x1C: /* Enter */ - return 13; + case 0x1C: /* Enter */ + return 13; - case 0x3A: /* Capslock */ - usb_lock ? (usb_lock = 0) : (usb_lock = 1); - break; - case 0x0E: /* Backspace */ - return 8; - case 0x0F: /* TAB */ - return 9; - case 0x77: /* Pause */ - break ; - default: - if(!usb_lock) { - return plain_map[keycode]; - } - else { - return shift_map[keycode]; - } + case 0x3A: /* Capslock */ + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); + break; + case 0x0E: /* Backspace */ + return 8; + case 0x0F: /* TAB */ + return 9; + case 0x77: /* Pause */ + break ; + default: + if(!kdb_usb_kbds[i].caps_lock) { + return plain_map[keycode]; + } + else { + return shift_map[keycode]; + } } } } + + /* no chars were returned from any of the USB keyboards */ + return -1; } #endif /* CONFIG_KDB_USB */ diff -pNaru linux.orig/arch/x86_64/kdb/kdba_io.c linux/arch/x86_64/kdb/kdba_io.c --- linux.orig/arch/x86_64/kdb/kdba_io.c 2007-11-09 11:37:46.000000000 -0800 +++ linux/arch/x86_64/kdb/kdba_io.c 2007-11-08 14:28:31.507644333 -0800 @@ -29,9 +29,10 @@ #endif #ifdef CONFIG_KDB_USB -struct kdb_usb_exchange kdb_usb_infos; -EXPORT_SYMBOL(kdb_usb_infos); +/* support up to 8 USB keyboards (probably excessive, but...) */ +#define KDB_USB_NUM_KEYBOARDS 8 +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; -/* get_usb_char - * This function drives the UHCI controller, - * fetch the USB scancode and decode it +/* + * kdb_usb_keyboard_attach() + * Attach a USB keyboard to kdb. */ -static int get_usb_char(void) +int +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) { - static int usb_lock; - unsigned char keycode, spec; - extern u_short plain_map[], shift_map[], ctrl_map[]; + int i; + int rc = -1; - /* Is USB initialized ? */ - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) - return -1; + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for a free index. If found, assign the keyboard to + * the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb) /* index is already assigned */ + continue; + + /* found a free array index */ + kdb_usb_kbds[i].urb = urb; + kdb_usb_kbds[i].buffer = buffer; + kdb_usb_kbds[i].poll_func = poll_func; - /* Transfer char if they are present */ - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); + rc = 0; /* success */ - spec = kdb_usb_infos.buffer[0]; - keycode = kdb_usb_infos.buffer[2]; - kdb_usb_infos.buffer[0] = (char)0; - kdb_usb_infos.buffer[2] = (char)0; + break; + } - if(kdb_usb_infos.buffer[3]) - return -1; + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); - /* A normal key is pressed, decode it */ - if(keycode) - keycode = kdb_usb_keycode[keycode]; - - /* 2 Keys pressed at one time ? */ - if (spec && keycode) { - switch(spec) - { - case 0x2: - case 0x20: /* Shift */ - return shift_map[keycode]; - case 0x1: - case 0x10: /* Ctrl */ - return ctrl_map[keycode]; - case 0x4: - case 0x40: /* Alt */ - break; - } - } - else { - if(keycode) { /* If only one key pressed */ - switch(keycode) - { - case 0x1C: /* Enter */ - return 13; - - case 0x3A: /* Capslock */ - usb_lock ? (usb_lock = 0) : (usb_lock = 1); - break; - case 0x0E: /* Backspace */ - return 8; - case 0x0F: /* TAB */ - return 9; - case 0x77: /* Pause */ - break ; - default: - if(!usb_lock) { - return plain_map[keycode]; - } - else { - return shift_map[keycode]; - } - } - } - } - return -1; +/* + * kdb_usb_keyboard_detach() + * Detach a USB keyboard from kdb. + */ +int +kdb_usb_keyboard_detach(struct urb *urb) +{ + int i; + int rc = -1; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for the index with the matching URB. If found, + * clear the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb != urb) + continue; + + /* found it, clear the index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].caps_lock = 0; + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); + +/* + * get_usb_char + * This function drives the USB attached keyboards. + * Fetch the USB scancode and decode it. + */ +static int +get_usb_char(void) +{ + int i; + int ret; + unsigned char keycode, spec; + extern u_short plain_map[], shift_map[], ctrl_map[]; + + /* + * Loop through all the USB keyboard(s) and return + * the first character obtained from them. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + /* skip uninitialized keyboard array entries */ + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || + !kdb_usb_kbds[i].poll_func) + continue; + + /* Transfer char */ + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (ret == -1) /* error or no characters, try the next kbd */ + continue; + + spec = kdb_usb_kbds[i].buffer[0]; + keycode = kdb_usb_kbds[i].buffer[2]; + kdb_usb_kbds[i].buffer[0] = (char)0; + kdb_usb_kbds[i].buffer[2] = (char)0; + + if(kdb_usb_kbds[i].buffer[3]) { + kdb_usb_kbds[i].buffer[3] = (char)0; + continue; + } + + /* A normal key is pressed, decode it */ + if(keycode) + keycode = kdb_usb_keycode[keycode]; + + /* 2 Keys pressed at one time ? */ + if (spec && keycode) { + switch(spec) + { + case 0x2: + case 0x20: /* Shift */ + return shift_map[keycode]; + case 0x1: + case 0x10: /* Ctrl */ + return ctrl_map[keycode]; + case 0x4: + case 0x40: /* Alt */ + break; + } + } else if (keycode) { /* If only one key pressed */ + switch(keycode) + { + case 0x1C: /* Enter */ + return 13; + + case 0x3A: /* Capslock */ + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); + break; + case 0x0E: /* Backspace */ + return 8; + case 0x0F: /* TAB */ + return 9; + case 0x77: /* Pause */ + break ; + default: + if(!kdb_usb_kbds[i].caps_lock) { + return plain_map[keycode]; + } + else { + return shift_map[keycode]; + } + } + } + } + + /* no chars were returned from any of the USB keyboards */ + + return -1; } #endif /* CONFIG_KDB_USB */ diff -pNaru linux.orig/drivers/hid/usbhid/hid-core.c linux/drivers/hid/usbhid/hid-core.c --- linux.orig/drivers/hid/usbhid/hid-core.c 2007-11-09 11:37:44.000000000 -0800 +++ linux/drivers/hid/usbhid/hid-core.c 2007-11-08 14:04:41.124958377 -0800 @@ -900,9 +900,12 @@ static void hid_disconnect(struct usb_in usbhid = hid->driver_data; #ifdef CONFIG_KDB_USB - /* Unlink the KDB USB struct */ - if (usbhid->urbin == kdb_usb_infos.urb) - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); + /* + * If the URB was for a Keyboard, detach it from kdb. + * If the URB was for another type of device, just + * allow kdb_usb_keyboard_detach() to silently fail. + */ + kdb_usb_keyboard_detach(usbhid->urbin); #endif spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ @@ -991,15 +994,20 @@ static int hid_probe(struct usb_interfac printk(": USB HID v%x.%02x %s [%s] on %s\n", hid->version >> 8, hid->version & 0xff, c, hid->name, path); -#ifdef CONFIG_KDB_USB - /* Initialization of the KDB structure */ +#ifdef CONFIG_KDB_USB + /* Attach USB keyboards to kdb */ if (!strcmp(c, "Keyboard")) { + int ret; struct usbhid_device *usbhid = hid->driver_data; - kdb_usb_infos.urb = usbhid->urbin; - kdb_usb_infos.buffer = usbhid->inbuf; - kdb_usb_infos.reset_timer = NULL; + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + + if (ret == -1) + printk(": FAILED to register keyboard (%s) " + "with KDB\n", path); } -#endif +#endif /* CONFIG_KDB_USB */ return 0; } diff -pNaru linux.orig/drivers/hid/usbhid/usbkbd.c linux/drivers/hid/usbhid/usbkbd.c --- linux.orig/drivers/hid/usbhid/usbkbd.c 2007-11-09 11:37:44.000000000 -0800 +++ linux/drivers/hid/usbhid/usbkbd.c 2007-11-08 14:04:41.148957819 -0800 @@ -292,12 +292,15 @@ static int usb_kbd_probe(struct usb_inte kbd->new, (maxp > 8 ? 8 : maxp), usb_kbd_irq, kbd, endpoint->bInterval); -#ifdef CONFIG_KDB_USB - /* Init the KDB structure */ - kdb_usb_infos.urb = kbd->irq; - kdb_usb_infos.buffer = kbd->new; - kdb_usb_infos.reset_timer = NULL; -#endif +#ifdef CONFIG_KDB_USB + /* Attach keyboard to kdb */ + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); + + kdb_usb_keyboard_attach(kbd->irq, kbd->new, + usb_hcd_get_kdb_poll_func(dev)); + +#endif /* CONFIG_KDB_USB */ + kbd->irq->transfer_dma = kbd->new_dma; kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -334,12 +337,11 @@ static void usb_kbd_disconnect(struct us struct usb_kbd *kbd = usb_get_intfdata (intf); usb_set_intfdata(intf, NULL); + if (kbd) { #ifdef CONFIG_KDB_USB - /* Unlink the KDB USB struct */ - if (kbd && kbd->irq == kdb_usb_infos.urb) - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); + /* Detach the keyboard from kdb */ + kdb_usb_keyboard_detach(kbd->irq); #endif /* CONFIG_KDB_USB */ - if (kbd) { usb_kill_urb(kbd->irq); input_unregister_device(kbd->dev); usb_kbd_free_mem(interface_to_usbdev(intf), kbd); diff -pNaru linux.orig/drivers/usb/core/hcd.c linux/drivers/usb/core/hcd.c --- linux.orig/drivers/usb/core/hcd.c 2007-10-09 13:31:38.000000000 -0700 +++ linux/drivers/usb/core/hcd.c 2007-11-08 14:04:42.228932671 -0800 @@ -1718,6 +1718,20 @@ usb_hcd_platform_shutdown(struct platfor } EXPORT_SYMBOL (usb_hcd_platform_shutdown); +#ifdef CONFIG_KDB_USB +void * +usb_hcd_get_kdb_poll_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_poll_char); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_USB_MON) diff -pNaru linux.orig/drivers/usb/core/hcd.h linux/drivers/usb/core/hcd.h --- linux.orig/drivers/usb/core/hcd.h 2007-10-09 13:31:38.000000000 -0700 +++ linux/drivers/usb/core/hcd.h 2007-11-08 14:04:42.248932205 -0800 @@ -202,6 +202,10 @@ struct hc_driver { int (*start_port_reset)(struct usb_hcd *, unsigned port_num); void (*hub_irq_enable)(struct usb_hcd *); /* Needed only if port-change IRQs are level-triggered */ +#ifdef CONFIG_KDB_USB + /* KDB poll function for this HC */ + int (*kdb_poll_char)(struct urb *urb); +#endif /* CONFIG_KDB_USB */ }; extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); diff -pNaru linux.orig/drivers/usb/host/ehci-hcd.c linux/drivers/usb/host/ehci-hcd.c --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-10-09 13:31:38.000000000 -0700 +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-08 14:04:42.272931646 -0800 @@ -916,6 +916,17 @@ static int ehci_get_frame (struct usb_hc ehci->periodic_size; } +#ifdef CONFIG_KDB_USB + +int +ehci_kdb_poll_char(struct urb *urb) +{ + /* routine not yet implemented */ + return -1; +} + +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC diff -pNaru linux.orig/drivers/usb/host/ehci-pci.c linux/drivers/usb/host/ehci-pci.c --- linux.orig/drivers/usb/host/ehci-pci.c 2007-10-09 13:31:38.000000000 -0700 +++ linux/drivers/usb/host/ehci-pci.c 2007-11-08 14:04:42.292931181 -0800 @@ -22,6 +22,10 @@ #error "This file is PCI bus glue. CONFIG_PCI must be defined." #endif +#ifdef CONFIG_KDB_USB +#include +#endif + /*-------------------------------------------------------------------------*/ /* called after powerup, by probe or system-pm "wakeup" */ @@ -367,6 +371,10 @@ static const struct hc_driver ehci_pci_h .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, + +#ifdef CONFIG_KDB_USB + .kdb_poll_char = ehci_kdb_poll_char, +#endif }; /*-------------------------------------------------------------------------*/ diff -pNaru linux.orig/drivers/usb/host/ohci-hcd.c linux/drivers/usb/host/ohci-hcd.c --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-09 11:37:44.000000000 -0800 +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-08 14:04:41.244955583 -0800 @@ -851,20 +851,14 @@ static void ohci_quirk_nec_worker(struct #ifdef CONFIG_KDB_USB -static void -ohci_kdb_poll (void * __ohci, struct urb *urb) +int +ohci_kdb_poll_char(struct urb *urb) { struct ohci_hcd *ohci; struct ohci_regs * regs; - /* - * NOTE - we use the ohci_hcd from the urb rather than the - * __ohci parameter (which is NULL anyway). This ensures - * that we will process the proper controller for the urb. - */ - - if (!urb) /* can happen if no keyboard attached */ - return; + if (!urb) /* should not happen */ + return -1; ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); regs = ohci->regs; @@ -873,23 +867,27 @@ ohci_kdb_poll (void * __ohci, struct urb if (urb->status != -EINPROGRESS) { if (usb_submit_urb (urb, GFP_ATOMIC)) - return; + return -1; /* make sure the HC registers are set correctly */ - writel (OHCI_INTR_WDH, ®s->intrenable); - writel (OHCI_INTR_WDH, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); + ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); // flush those pci writes - (void) readl (&ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); } if (ohci->hcca->done_head) { dl_done_list_kdb (ohci, urb); - writel (OHCI_INTR_WDH, ®s->intrstatus); + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); // flush the pci write - (void) readl (&ohci->regs->control); + (void) ohci_readl (ohci, &ohci->regs->control); + + return 0; } + + return -1; } #endif /* CONFIG_KDB_USB */ diff -pNaru linux.orig/drivers/usb/host/ohci-pci.c linux/drivers/usb/host/ohci-pci.c --- linux.orig/drivers/usb/host/ohci-pci.c 2007-11-09 11:37:44.000000000 -0800 +++ linux/drivers/usb/host/ohci-pci.c 2007-11-08 14:04:41.268955024 -0800 @@ -18,7 +18,7 @@ #error "This file is PCI bus glue. CONFIG_PCI must be defined." #endif -#ifdef CONFIG_KDB_USB +#ifdef CONFIG_KDB_USB #include #endif @@ -219,12 +219,7 @@ static int __devinit ohci_pci_start (str ohci_err (ohci, "can't start\n"); ohci_stop (hcd); } -#ifdef CONFIG_KDB_USB - if (ret >= 0) { - kdb_usb_infos.poll_func = ohci_kdb_poll; - kdb_usb_infos.uhci = NULL; /* not used */ - } -#endif + return ret; } @@ -363,6 +358,9 @@ static const struct hc_driver ohci_pci_h .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = ohci_kdb_poll_char, +#endif }; /*-------------------------------------------------------------------------*/ diff -pNaru linux.orig/include/linux/kdb.h linux/include/linux/kdb.h --- linux.orig/include/linux/kdb.h 2007-11-09 11:37:44.000000000 -0800 +++ linux/include/linux/kdb.h 2007-11-08 14:04:41.420951485 -0800 @@ -140,16 +140,12 @@ extern void smp_kdb_stop(void); #endif /* CONFIG_SMP */ #ifdef CONFIG_KDB_USB + #include -struct kdb_usb_exchange { - void *uhci; /* pointer to the UHCI structure */ - struct urb *urb; /* pointer to the URB */ - unsigned char *buffer; /* pointer to buffer */ - void (*poll_func)(void *, struct urb *); /* pointer to the polling function */ - void (*reset_timer)(void); /* pointer to the reset timer function */ -}; -extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */ +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); +extern int kdb_usb_keyboard_detach(struct urb *urb); + #endif /* CONFIG_KDB_USB */ static inline diff -pNaru linux.orig/include/linux/kdbprivate.h linux/include/linux/kdbprivate.h --- linux.orig/include/linux/kdbprivate.h 2007-11-09 11:37:44.000000000 -0800 +++ linux/include/linux/kdbprivate.h 2007-11-08 14:04:41.460950554 -0800 @@ -482,4 +482,15 @@ extern char kdb_prompt_str[]; #define KDB_WORD_SIZE ((int)sizeof(kdb_machreg_t)) +#ifdef CONFIG_KDB_USB +#include + +struct kdb_usb_kbd_info { + struct urb *urb; /* pointer to the URB */ + unsigned char *buffer; /* pointer to the kbd char buffer */ + int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int caps_lock; /* state of the caps lock for this keyboard */ +}; +#endif /* CONFIG_KDB_USB */ + #endif /* !_KDBPRIVATE_H */ --- --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Fri Nov 9 14:19:26 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 09 Nov 2007 14:19:33 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lA9MJPXo009852 for ; Fri, 9 Nov 2007 14:19:26 -0800 Received: from [134.15.0.106] (mtv-vpn-sw-corp-0-106.corp.sgi.com [134.15.0.106]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lA9MJSke027723; Fri, 9 Nov 2007 14:19:28 -0800 Message-ID: <4734DCFF.3000106@sgi.com> Date: Fri, 09 Nov 2007 14:19:43 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: Aaron Young CC: kdb@oss.sgi.com Subject: Re: [PATCH] New USB Keyboard interface for KDB References: <200711092139.lA9LdBwF5074249@kluge.engr.sgi.com> In-Reply-To: <200711092139.lA9LdBwF5074249@kluge.engr.sgi.com> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1274 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Aaron Young wrote: > This patch implements a new KDB interface for USB keyboards > which fixes the following problems: > > 1. Currently KDB is only "OHCI" type USB aware. If a keyboard is attached > via a USB2.0 hub, the Linux kernel EHCI driver is used instead of OHCI, but > kdb will still attempt to use the OHCI driver poll interface to > read a character from the keyboard - this results in a crash from > within kdb and, hence, kdb is unuseable. > > This patch allows KDB to work with any Host Contoller driver > and call the correct HC driver poll routine (as long as the > HC driver provides a .kdb_poll_char routine via it's > associated hc_driver struct). > If a HC driver is managing a keyboard, but doesn't provide a > valid .kdb_poll_char routine, the keyboard will be ignored by KDB. > > 2. Hotplug - currently, if a USB keyboard is unplugged and plugged back > in, KDB loses track and no longer recognizes the keyboard for use from KDB. > This is because the "kdb_usb_infos" struct was getting zeroed and the > .poll_func field set to NULL on hotunplugs (and not set to something > valid on hotplugs) > > Hotplugged keyboards are now recognized by KDB. > > 3. Currently KDB can only make use of 1 USB type keyboard. This is because > of the single "kdb_usb_infos" structure interface - which can only describe > a single keyboard/urb. > > New code can handle up to 8 attached keyboards - input is multiplexed > from all of them while in kdb. The number of supported USB keyboards can > easily be changed via the KDB_USB_NUM_KEYBOARDS def in appropriate > arch/XXX/kdb//kdba_io.c file. > > > General notes about the new code: > > The new USB interface is composed of two new routines which > HID drivers need to call when configuring USB keyboards: > > kdb_usb_keyboard_attach() - to attach a USB keyboard to KDB > kdb_usb_keyboard_detach() - to detach a USB keyboard from KDB > > These should be called from the hotplug interfaces so that hotplugs/ > unplugs keep KDB up-to-date on what keyboards are on the system. > > Each USB Host Controller driver which could manage keyboards needs > to add a .kdb_poll_char entry to it's associated hc_driver struct and > and, of course, provide the routine to poll a keyboard's URB for characters. > The OHCI implementation is complete and there. UHCI is completely > missing at this point and EHCI is partially there - i.e. EHCI provides > the .kdb_poll_char entry, but the associated routine, ehci_kdb_poll_char() > is not yet implemented (and just returns -1 for now). I plan to work > on the EHCI poll code next. I hope to have a subsequent patch for this > very soon. > > Issues: > > While testing I noticed some issues when using hubs to attach > USB keyboards. When multiple keyboards are attached via a USB1.1 > hub, only one of the keyboards is operational from kdb - not sure > why. It's probably a shortcoming of the OHCI poll character code. > Also, it appears hotplug of USB1.1 hubs doesn't work right in Linux > and the HID hotplug interfaces are not called for the attached keyboards. > Hotplug does work correctly with USB2.0 hubs however. > > When keyboard(s) are attached directly to USB ports (with no hubs), I > could find no issues - hotplug/unplug, mulitplexing all appear to work > properly. > > Testing: > > These changes have only been tested on a ia64 machine containing > OHCI/EHCI style USB controllers. Additional testing on other archs > and USB configs by others would be appreciated. > > > Patch is against 2.6.23-rc8 (should be applied after kdb-4.4-2.6.23-*.1 patch set) Well, actually i generated this patch for you against linux-2.6.23 and the 2.6.23 version of kdb patchset. I did basic testing on ia64, x86_64, and i386, but i did not have equipments to test new feature of USB keyboards/mice though. Thanks, - jay > > Signed-off-by: Aaron Young (ayoung@sgi.com) > > --- > > diff -pNaru linux.orig/arch/i386/kdb/kdba_io.c linux/arch/i386/kdb/kdba_io.c > --- linux.orig/arch/i386/kdb/kdba_io.c 2007-11-09 11:37:45.000000000 -0800 > +++ linux/arch/i386/kdb/kdba_io.c 2007-11-08 14:26:07.710994431 -0800 > @@ -29,9 +29,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + rc = 0; /* success */ > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + break; > + } > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > - > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > - case 0x2: > - case 0x20: /* Shift */ > - return shift_map[keycode]; > - case 0x1: > - case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > - case 0x4: > - case 0x40: /* Alt */ > - break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > - switch(keycode) > - { > - case 0x1C: /* Enter */ > - return 13; > - > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > - } > - } > - } > - return -1; > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > + > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > + case 0x2: > + case 0x20: /* Shift */ > + return shift_map[keycode]; > + case 0x1: > + case 0x10: /* Ctrl */ > + return ctrl_map[keycode]; > + case 0x4: > + case 0x40: /* Alt */ > + break; > + } > + } else if (keycode) { /* If only one key pressed */ > + switch(keycode) > + { > + case 0x1C: /* Enter */ > + return 13; > + > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > + } > + } > + } > + > + /* no chars were returned from any of the USB keyboards */ > + > + return -1; > } > #endif /* CONFIG_KDB_USB */ > > diff -pNaru linux.orig/arch/ia64/kdb/kdba_io.c linux/arch/ia64/kdb/kdba_io.c > --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-09 11:37:47.000000000 -0800 > +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-08 14:31:06.500022083 -0800 > @@ -39,9 +39,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -62,39 +63,122 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if (!kdb_usb_infos.poll_func || !kdb_usb_infos.urb || !kdb_usb_infos.buffer) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + rc = 0; /* success */ > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > + > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > case 0x2: > case 0x20: /* Shift */ > return shift_map[keycode]; > @@ -104,34 +188,35 @@ static int get_usb_char(void) > case 0x4: > case 0x40: /* Alt */ > break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > + } > + } else if (keycode) { /* If only one key pressed */ > switch(keycode) > { > - case 0x1C: /* Enter */ > - return 13; > + case 0x1C: /* Enter */ > + return 13; > > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > } > } > } > + > + /* no chars were returned from any of the USB keyboards */ > + > return -1; > } > #endif /* CONFIG_KDB_USB */ > diff -pNaru linux.orig/arch/x86_64/kdb/kdba_io.c linux/arch/x86_64/kdb/kdba_io.c > --- linux.orig/arch/x86_64/kdb/kdba_io.c 2007-11-09 11:37:46.000000000 -0800 > +++ linux/arch/x86_64/kdb/kdba_io.c 2007-11-08 14:28:31.507644333 -0800 > @@ -29,9 +29,10 @@ > #endif > > #ifdef CONFIG_KDB_USB > -struct kdb_usb_exchange kdb_usb_infos; > > -EXPORT_SYMBOL(kdb_usb_infos); > +/* support up to 8 USB keyboards (probably excessive, but...) */ > +#define KDB_USB_NUM_KEYBOARDS 8 > +struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; > > static unsigned char kdb_usb_keycode[256] = { > 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, > @@ -52,77 +53,161 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > -/* get_usb_char > - * This function drives the UHCI controller, > - * fetch the USB scancode and decode it > +/* > + * kdb_usb_keyboard_attach() > + * Attach a USB keyboard to kdb. > */ > -static int get_usb_char(void) > +int > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > { > - static int usb_lock; > - unsigned char keycode, spec; > - extern u_short plain_map[], shift_map[], ctrl_map[]; > + int i; > + int rc = -1; > > - /* Is USB initialized ? */ > - if(!kdb_usb_infos.poll_func || !kdb_usb_infos.urb) > - return -1; > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + kdb_usb_kbds[i].urb = urb; > + kdb_usb_kbds[i].buffer = buffer; > + kdb_usb_kbds[i].poll_func = poll_func; > > - /* Transfer char if they are present */ > - (*kdb_usb_infos.poll_func)(kdb_usb_infos.uhci, (struct urb *)kdb_usb_infos.urb); > + rc = 0; /* success */ > > - spec = kdb_usb_infos.buffer[0]; > - keycode = kdb_usb_infos.buffer[2]; > - kdb_usb_infos.buffer[0] = (char)0; > - kdb_usb_infos.buffer[2] = (char)0; > + break; > + } > > - if(kdb_usb_infos.buffer[3]) > - return -1; > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > > - /* A normal key is pressed, decode it */ > - if(keycode) > - keycode = kdb_usb_keycode[keycode]; > - > - /* 2 Keys pressed at one time ? */ > - if (spec && keycode) { > - switch(spec) > - { > - case 0x2: > - case 0x20: /* Shift */ > - return shift_map[keycode]; > - case 0x1: > - case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > - case 0x4: > - case 0x40: /* Alt */ > - break; > - } > - } > - else { > - if(keycode) { /* If only one key pressed */ > - switch(keycode) > - { > - case 0x1C: /* Enter */ > - return 13; > - > - case 0x3A: /* Capslock */ > - usb_lock ? (usb_lock = 0) : (usb_lock = 1); > - break; > - case 0x0E: /* Backspace */ > - return 8; > - case 0x0F: /* TAB */ > - return 9; > - case 0x77: /* Pause */ > - break ; > - default: > - if(!usb_lock) { > - return plain_map[keycode]; > - } > - else { > - return shift_map[keycode]; > - } > - } > - } > - } > - return -1; > +/* > + * kdb_usb_keyboard_detach() > + * Detach a USB keyboard from kdb. > + */ > +int > +kdb_usb_keyboard_detach(struct urb *urb) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for the index with the matching URB. If found, > + * clear the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb != urb) > + continue; > + > + /* found it, clear the index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].caps_lock = 0; > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_keyboard_detach); > + > +/* > + * get_usb_char > + * This function drives the USB attached keyboards. > + * Fetch the USB scancode and decode it. > + */ > +static int > +get_usb_char(void) > +{ > + int i; > + int ret; > + unsigned char keycode, spec; > + extern u_short plain_map[], shift_map[], ctrl_map[]; > + > + /* > + * Loop through all the USB keyboard(s) and return > + * the first character obtained from them. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + /* skip uninitialized keyboard array entries */ > + if (!kdb_usb_kbds[i].urb || !kdb_usb_kbds[i].buffer || > + !kdb_usb_kbds[i].poll_func) > + continue; > + > + /* Transfer char */ > + ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (ret == -1) /* error or no characters, try the next kbd */ > + continue; > + > + spec = kdb_usb_kbds[i].buffer[0]; > + keycode = kdb_usb_kbds[i].buffer[2]; > + kdb_usb_kbds[i].buffer[0] = (char)0; > + kdb_usb_kbds[i].buffer[2] = (char)0; > + > + if(kdb_usb_kbds[i].buffer[3]) { > + kdb_usb_kbds[i].buffer[3] = (char)0; > + continue; > + } > + > + /* A normal key is pressed, decode it */ > + if(keycode) > + keycode = kdb_usb_keycode[keycode]; > + > + /* 2 Keys pressed at one time ? */ > + if (spec && keycode) { > + switch(spec) > + { > + case 0x2: > + case 0x20: /* Shift */ > + return shift_map[keycode]; > + case 0x1: > + case 0x10: /* Ctrl */ > + return ctrl_map[keycode]; > + case 0x4: > + case 0x40: /* Alt */ > + break; > + } > + } else if (keycode) { /* If only one key pressed */ > + switch(keycode) > + { > + case 0x1C: /* Enter */ > + return 13; > + > + case 0x3A: /* Capslock */ > + kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > + break; > + case 0x0E: /* Backspace */ > + return 8; > + case 0x0F: /* TAB */ > + return 9; > + case 0x77: /* Pause */ > + break ; > + default: > + if(!kdb_usb_kbds[i].caps_lock) { > + return plain_map[keycode]; > + } > + else { > + return shift_map[keycode]; > + } > + } > + } > + } > + > + /* no chars were returned from any of the USB keyboards */ > + > + return -1; > } > #endif /* CONFIG_KDB_USB */ > > diff -pNaru linux.orig/drivers/hid/usbhid/hid-core.c linux/drivers/hid/usbhid/hid-core.c > --- linux.orig/drivers/hid/usbhid/hid-core.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/hid/usbhid/hid-core.c 2007-11-08 14:04:41.124958377 -0800 > @@ -900,9 +900,12 @@ static void hid_disconnect(struct usb_in > usbhid = hid->driver_data; > > #ifdef CONFIG_KDB_USB > - /* Unlink the KDB USB struct */ > - if (usbhid->urbin == kdb_usb_infos.urb) > - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); > + /* > + * If the URB was for a Keyboard, detach it from kdb. > + * If the URB was for another type of device, just > + * allow kdb_usb_keyboard_detach() to silently fail. > + */ > + kdb_usb_keyboard_detach(usbhid->urbin); > #endif > > spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ > @@ -991,15 +994,20 @@ static int hid_probe(struct usb_interfac > printk(": USB HID v%x.%02x %s [%s] on %s\n", > hid->version >> 8, hid->version & 0xff, c, hid->name, path); > > -#ifdef CONFIG_KDB_USB > - /* Initialization of the KDB structure */ > +#ifdef CONFIG_KDB_USB > + /* Attach USB keyboards to kdb */ > if (!strcmp(c, "Keyboard")) { > + int ret; > struct usbhid_device *usbhid = hid->driver_data; > - kdb_usb_infos.urb = usbhid->urbin; > - kdb_usb_infos.buffer = usbhid->inbuf; > - kdb_usb_infos.reset_timer = NULL; > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + > + if (ret == -1) > + printk(": FAILED to register keyboard (%s) " > + "with KDB\n", path); > } > -#endif > +#endif /* CONFIG_KDB_USB */ > > return 0; > } > diff -pNaru linux.orig/drivers/hid/usbhid/usbkbd.c linux/drivers/hid/usbhid/usbkbd.c > --- linux.orig/drivers/hid/usbhid/usbkbd.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/hid/usbhid/usbkbd.c 2007-11-08 14:04:41.148957819 -0800 > @@ -292,12 +292,15 @@ static int usb_kbd_probe(struct usb_inte > kbd->new, (maxp > 8 ? 8 : maxp), > usb_kbd_irq, kbd, endpoint->bInterval); > > -#ifdef CONFIG_KDB_USB > - /* Init the KDB structure */ > - kdb_usb_infos.urb = kbd->irq; > - kdb_usb_infos.buffer = kbd->new; > - kdb_usb_infos.reset_timer = NULL; > -#endif > +#ifdef CONFIG_KDB_USB > + /* Attach keyboard to kdb */ > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + > + kdb_usb_keyboard_attach(kbd->irq, kbd->new, > + usb_hcd_get_kdb_poll_func(dev)); > + > +#endif /* CONFIG_KDB_USB */ > + > kbd->irq->transfer_dma = kbd->new_dma; > kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > > @@ -334,12 +337,11 @@ static void usb_kbd_disconnect(struct us > struct usb_kbd *kbd = usb_get_intfdata (intf); > > usb_set_intfdata(intf, NULL); > + if (kbd) { > #ifdef CONFIG_KDB_USB > - /* Unlink the KDB USB struct */ > - if (kbd && kbd->irq == kdb_usb_infos.urb) > - memset(&kdb_usb_infos, 0, sizeof(kdb_usb_infos)); > + /* Detach the keyboard from kdb */ > + kdb_usb_keyboard_detach(kbd->irq); > #endif /* CONFIG_KDB_USB */ > - if (kbd) { > usb_kill_urb(kbd->irq); > input_unregister_device(kbd->dev); > usb_kbd_free_mem(interface_to_usbdev(intf), kbd); > diff -pNaru linux.orig/drivers/usb/core/hcd.c linux/drivers/usb/core/hcd.c > --- linux.orig/drivers/usb/core/hcd.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/core/hcd.c 2007-11-08 14:04:42.228932671 -0800 > @@ -1718,6 +1718,20 @@ usb_hcd_platform_shutdown(struct platfor > } > EXPORT_SYMBOL (usb_hcd_platform_shutdown); > > +#ifdef CONFIG_KDB_USB > +void * > +usb_hcd_get_kdb_poll_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_poll_char); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > +#endif /* CONFIG_KDB_USB */ > + > /*-------------------------------------------------------------------------*/ > > #if defined(CONFIG_USB_MON) > diff -pNaru linux.orig/drivers/usb/core/hcd.h linux/drivers/usb/core/hcd.h > --- linux.orig/drivers/usb/core/hcd.h 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/core/hcd.h 2007-11-08 14:04:42.248932205 -0800 > @@ -202,6 +202,10 @@ struct hc_driver { > int (*start_port_reset)(struct usb_hcd *, unsigned port_num); > void (*hub_irq_enable)(struct usb_hcd *); > /* Needed only if port-change IRQs are level-triggered */ > +#ifdef CONFIG_KDB_USB > + /* KDB poll function for this HC */ > + int (*kdb_poll_char)(struct urb *urb); > +#endif /* CONFIG_KDB_USB */ > }; > > extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags); > diff -pNaru linux.orig/drivers/usb/host/ehci-hcd.c linux/drivers/usb/host/ehci-hcd.c > --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-08 14:04:42.272931646 -0800 > @@ -916,6 +916,17 @@ static int ehci_get_frame (struct usb_hc > ehci->periodic_size; > } > > +#ifdef CONFIG_KDB_USB > + > +int > +ehci_kdb_poll_char(struct urb *urb) > +{ > + /* routine not yet implemented */ > + return -1; > +} > + > +#endif /* CONFIG_KDB_USB */ > + > /*-------------------------------------------------------------------------*/ > > #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC > diff -pNaru linux.orig/drivers/usb/host/ehci-pci.c linux/drivers/usb/host/ehci-pci.c > --- linux.orig/drivers/usb/host/ehci-pci.c 2007-10-09 13:31:38.000000000 -0700 > +++ linux/drivers/usb/host/ehci-pci.c 2007-11-08 14:04:42.292931181 -0800 > @@ -22,6 +22,10 @@ > #error "This file is PCI bus glue. CONFIG_PCI must be defined." > #endif > > +#ifdef CONFIG_KDB_USB > +#include > +#endif > + > /*-------------------------------------------------------------------------*/ > > /* called after powerup, by probe or system-pm "wakeup" */ > @@ -367,6 +371,10 @@ static const struct hc_driver ehci_pci_h > .hub_control = ehci_hub_control, > .bus_suspend = ehci_bus_suspend, > .bus_resume = ehci_bus_resume, > + > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = ehci_kdb_poll_char, > +#endif > }; > > /*-------------------------------------------------------------------------*/ > diff -pNaru linux.orig/drivers/usb/host/ohci-hcd.c linux/drivers/usb/host/ohci-hcd.c > --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-08 14:04:41.244955583 -0800 > @@ -851,20 +851,14 @@ static void ohci_quirk_nec_worker(struct > > #ifdef CONFIG_KDB_USB > > -static void > -ohci_kdb_poll (void * __ohci, struct urb *urb) > +int > +ohci_kdb_poll_char(struct urb *urb) > { > struct ohci_hcd *ohci; > struct ohci_regs * regs; > > - /* > - * NOTE - we use the ohci_hcd from the urb rather than the > - * __ohci parameter (which is NULL anyway). This ensures > - * that we will process the proper controller for the urb. > - */ > - > - if (!urb) /* can happen if no keyboard attached */ > - return; > + if (!urb) /* should not happen */ > + return -1; > > ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); > regs = ohci->regs; > @@ -873,23 +867,27 @@ ohci_kdb_poll (void * __ohci, struct urb > if (urb->status != -EINPROGRESS) { > > if (usb_submit_urb (urb, GFP_ATOMIC)) > - return; > + return -1; > > /* make sure the HC registers are set correctly */ > - writel (OHCI_INTR_WDH, ®s->intrenable); > - writel (OHCI_INTR_WDH, ®s->intrstatus); > - writel (OHCI_INTR_MIE, ®s->intrenable); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); > + ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); > > // flush those pci writes > - (void) readl (&ohci->regs->control); > + (void) ohci_readl (ohci, &ohci->regs->control); > } > > if (ohci->hcca->done_head) { > dl_done_list_kdb (ohci, urb); > - writel (OHCI_INTR_WDH, ®s->intrstatus); > + ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrstatus); > // flush the pci write > - (void) readl (&ohci->regs->control); > + (void) ohci_readl (ohci, &ohci->regs->control); > + > + return 0; > } > + > + return -1; > } > > #endif /* CONFIG_KDB_USB */ > diff -pNaru linux.orig/drivers/usb/host/ohci-pci.c linux/drivers/usb/host/ohci-pci.c > --- linux.orig/drivers/usb/host/ohci-pci.c 2007-11-09 11:37:44.000000000 -0800 > +++ linux/drivers/usb/host/ohci-pci.c 2007-11-08 14:04:41.268955024 -0800 > @@ -18,7 +18,7 @@ > #error "This file is PCI bus glue. CONFIG_PCI must be defined." > #endif > > -#ifdef CONFIG_KDB_USB > +#ifdef CONFIG_KDB_USB > #include > #endif > > @@ -219,12 +219,7 @@ static int __devinit ohci_pci_start (str > ohci_err (ohci, "can't start\n"); > ohci_stop (hcd); > } > -#ifdef CONFIG_KDB_USB > - if (ret >= 0) { > - kdb_usb_infos.poll_func = ohci_kdb_poll; > - kdb_usb_infos.uhci = NULL; /* not used */ > - } > -#endif > + > return ret; > } > > @@ -363,6 +358,9 @@ static const struct hc_driver ohci_pci_h > .bus_resume = ohci_bus_resume, > #endif > .start_port_reset = ohci_start_port_reset, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = ohci_kdb_poll_char, > +#endif > }; > > /*-------------------------------------------------------------------------*/ > diff -pNaru linux.orig/include/linux/kdb.h linux/include/linux/kdb.h > --- linux.orig/include/linux/kdb.h 2007-11-09 11:37:44.000000000 -0800 > +++ linux/include/linux/kdb.h 2007-11-08 14:04:41.420951485 -0800 > @@ -140,16 +140,12 @@ extern void smp_kdb_stop(void); > #endif /* CONFIG_SMP */ > > #ifdef CONFIG_KDB_USB > + > #include > > -struct kdb_usb_exchange { > - void *uhci; /* pointer to the UHCI structure */ > - struct urb *urb; /* pointer to the URB */ > - unsigned char *buffer; /* pointer to buffer */ > - void (*poll_func)(void *, struct urb *); /* pointer to the polling function */ > - void (*reset_timer)(void); /* pointer to the reset timer function */ > -}; > -extern struct kdb_usb_exchange kdb_usb_infos; /* KDB common structure */ > +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > +extern int kdb_usb_keyboard_detach(struct urb *urb); > + > #endif /* CONFIG_KDB_USB */ > > static inline > diff -pNaru linux.orig/include/linux/kdbprivate.h linux/include/linux/kdbprivate.h > --- linux.orig/include/linux/kdbprivate.h 2007-11-09 11:37:44.000000000 -0800 > +++ linux/include/linux/kdbprivate.h 2007-11-08 14:04:41.460950554 -0800 > @@ -482,4 +482,15 @@ extern char kdb_prompt_str[]; > > #define KDB_WORD_SIZE ((int)sizeof(kdb_machreg_t)) > > +#ifdef CONFIG_KDB_USB > +#include > + > +struct kdb_usb_kbd_info { > + struct urb *urb; /* pointer to the URB */ > + unsigned char *buffer; /* pointer to the kbd char buffer */ > + int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ > + int caps_lock; /* state of the caps lock for this keyboard */ > +}; > +#endif /* CONFIG_KDB_USB */ > + > #endif /* !_KDBPRIVATE_H */ > > --- > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Mon Nov 12 10:58:53 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 12 Nov 2007 10:58:58 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lACIwqlF013183 for ; Mon, 12 Nov 2007 10:58:53 -0800 Received: from [150.166.8.78] (aware.engr.sgi.com [150.166.8.78]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lACIbpK95898926; Mon, 12 Nov 2007 10:37:51 -0800 (PST) Message-ID: <47389DA0.1000700@sgi.com> Date: Mon, 12 Nov 2007 10:38:24 -0800 From: Jay Lan User-Agent: Thunderbird 2.0.0.6 (X11/20070801) MIME-Version: 1.0 To: KDB Subject: kdb patchset for linux-2.6.24-rc1 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1275 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Hi, Sorry it took so long to get KDB upgrade to 2.6.24-rc1 out. The x86 merge was a big thing to KDB. I merged kdb-v4.4-2.6.23-i386-1 and kdb-v4.4-2.6.23-x86_64-1 into kdb-v4.4-2.6.24-rc1-x86-1. During the merge, if there are same file names under i386 and x86_64, these files are now saved as _32.[ch] and _64.[ch] respectively under arch/x86/kdb or include/asm-x86. There are a few files that are specific to x86 in general, but not specific to i386 or x86_64 in particular. Those files were placed at the common directory before. I kept them at the common directory for now trying to preserve old look in this first attempt of mering. Please report any problem or strange behavior to this mailing list. Thanks, - jay --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jidong.xiao@gmail.com Mon Nov 12 21:47:14 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 12 Nov 2007 21:47:20 -0800 (PST) Received: from rv-out-0910.google.com (rv-out-0910.google.com [209.85.198.190]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAD5lB7U029184 for ; Mon, 12 Nov 2007 21:47:14 -0800 Received: by rv-out-0910.google.com with SMTP id k20so1041420rvb for ; Mon, 12 Nov 2007 21:47:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=Scyc0S4J1SrLmeKi0Pmu7tDwVYmxxKR8VZFusroaPuM=; b=TN/S1Gno7upOC9HLsJZW3hh8mQU+TaC8nwpGNyFfJJdilgmrYaA7gt3C9rCXFpUaYhgKhVRYfHAe9afplf0z/YybZTI54Jv7XvqgVLsCURoyyuoa0On+q82/2c4yBrrQgwko2WPjg8o6cS1pz15QXITdXxl60AL6cqEzo7u4ogw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=q7YaZFcJAXeLFAeCvkNA87AM/nKGqoGI5nBkccIxF6nRjwNPcO7GMsYkLVglETP1lpiWpoiJRksZRbaouOSogBiq7b9J7CmZ2YtoT+IW25fbHhyjnz8Qe2aecO+z8ClLPCJxAMQTTcOWMecyqjvzWzj+Zz46OCH5zr+3M/ISBLA= Received: by 10.142.77.11 with SMTP id z11mr1092802wfa.1194932837245; Mon, 12 Nov 2007 21:47:17 -0800 (PST) Received: by 10.142.14.21 with HTTP; Mon, 12 Nov 2007 21:47:17 -0800 (PST) Message-ID: <4104961b0711122147o4913845fl4db7e188c1a94347@mail.gmail.com> Date: Tue, 13 Nov 2007 13:47:17 +0800 From: "jidong xiao" To: "Jay Lan" Subject: Re: kdb patchset for linux-2.6.24-rc1 Cc: KDB In-Reply-To: <47389DA0.1000700@sgi.com> MIME-Version: 1.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Disposition: inline References: <47389DA0.1000700@sgi.com> X-archive-position: 1276 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jidong.xiao@gmail.com Precedence: bulk X-list: kdb On Nov 13, 2007 2:38 AM, Jay Lan wrote: > Hi, > > Sorry it took so long to get KDB upgrade to 2.6.24-rc1 out. > The x86 merge was a big thing to KDB. I merged kdb-v4.4-2.6.23-i386-1 > and kdb-v4.4-2.6.23-x86_64-1 into kdb-v4.4-2.6.24-rc1-x86-1. > Any benefit from the merging? Regards Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Tue Nov 13 09:41:21 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 13 Nov 2007 09:41:26 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lADHfHOv009231 for ; Tue, 13 Nov 2007 09:41:20 -0800 Received: from [134.15.0.64] (mtv-vpn-sw-corp-0-64.corp.sgi.com [134.15.0.64]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lADHfKke008919; Tue, 13 Nov 2007 09:41:21 -0800 Message-ID: <4739CC40.6010908@sgi.com> Date: Tue, 13 Nov 2007 08:09:36 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: jidong xiao CC: KDB Subject: Re: kdb patchset for linux-2.6.24-rc1 References: <47389DA0.1000700@sgi.com> <4104961b0711122147o4913845fl4db7e188c1a94347@mail.gmail.com> In-Reply-To: <4104961b0711122147o4913845fl4db7e188c1a94347@mail.gmail.com> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1277 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb jidong xiao wrote: > On Nov 13, 2007 2:38 AM, Jay Lan wrote: >> Hi, >> >> Sorry it took so long to get KDB upgrade to 2.6.24-rc1 out. >> The x86 merge was a big thing to KDB. I merged kdb-v4.4-2.6.23-i386-1 >> and kdb-v4.4-2.6.23-x86_64-1 into kdb-v4.4-2.6.24-rc1-x86-1. >> > > Any benefit from the merging? Well, linux 2.6.24-rc1 merged arch/i386 and arch/x86_64 into arch/x86. (The arch/i386 and arch/x86_64 are completely gone in 2.6.24-rc2.) As a result, arch/{i386,x86_64}/kdb need to merge. I think it looks cleaner to release a single KDB -x86 patch to reflect the changes. Thanks, - jay > > Regards > Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Tue Nov 13 13:42:34 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 13 Nov 2007 13:42:57 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lADLgWA4013784 for ; Tue, 13 Nov 2007 13:42:33 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lADLgcK95841951 for ; Tue, 13 Nov 2007 13:42:38 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lADLgcie5542388 for kdb@oss.sgi.com; Tue, 13 Nov 2007 13:42:38 -0800 (PST) Date: Tue, 13 Nov 2007 13:42:38 -0800 (PST) From: Aaron Young Message-Id: <200711132142.lADLgcie5542388@kluge.engr.sgi.com> To: kdb@oss.sgi.com Subject: [PATCH] KDB USB EHCI Support X-archive-position: 1278 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb This patch adds support to KDB for USB keyboards attached via EHCI. This happens when USB keyboards are connected via a USB2.0 hub forcing the Linux kernel EHCI driver to take control instead of the "companion" OHCI or UHCI drivers. It also adds a new boot parameter, "kdbnousb", which when set will disable KDB from configuring and using USB keyboards. This may prove useful if someone experiences a problem with KDB and USB keyboards by allowing KDB to still be used via a serial attached keyboard. Patch is against 2.6.23 (and should be applied after kdb-v4.4-2.6.23-*-2 patch set) Signed-off-by: Aaron Young (ayoung@sgi.com) Index: linux/arch/i386/kdb/kdba_io.c =================================================================== --- linux.orig/arch/i386/kdb/kdba_io.c 2007-11-13 13:52:15.000000000 -0600 +++ linux/arch/i386/kdb/kdba_io.c 2007-11-13 14:08:36.856610202 -0600 @@ -34,6 +34,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -63,6 +65,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -97,6 +102,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -134,6 +142,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/arch/ia64/kdb/kdba_io.c =================================================================== --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-13 13:52:16.000000000 -0600 +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-13 14:09:07.484469037 -0600 @@ -44,6 +44,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -73,6 +75,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -107,6 +112,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -144,6 +152,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/arch/x86_64/kdb/kdba_io.c =================================================================== --- linux.orig/arch/x86_64/kdb/kdba_io.c 2007-11-13 13:52:15.000000000 -0600 +++ linux/arch/x86_64/kdb/kdba_io.c 2007-11-13 14:09:43.601018582 -0600 @@ -34,6 +34,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -63,6 +65,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -97,6 +102,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -134,6 +142,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/drivers/usb/host/ehci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-11-13 13:52:15.000000000 -0600 +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-13 14:10:30.446918384 -0600 @@ -921,7 +921,24 @@ int ehci_kdb_poll_char(struct urb *urb) { - /* routine not yet implemented */ + struct ehci_hcd *ehci; + + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) + return -1; + + ehci = (struct ehci_hcd *) hcd_to_ehci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ehci) + return -1; + + if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) + return -1; + + if (qh_completions_kdb(ehci, urb->hcpriv, urb)) + return 0; + return -1; } Index: linux/drivers/usb/host/ehci-q.c =================================================================== --- linux.orig/drivers/usb/host/ehci-q.c 2007-10-09 15:31:38.000000000 -0500 +++ linux/drivers/usb/host/ehci-q.c 2007-11-13 14:11:02.490953190 -0600 @@ -444,6 +444,212 @@ return count; } +#ifdef CONFIG_KDB_USB +/* + * This routine is basically a copy of qh_completions() for use by KDB. + * It is modified to only work on qtds which are associated + * with 'kdburb'. Also, there are some fixups related to locking. + */ +unsigned +qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb) +{ + struct ehci_qtd *last = NULL, *end = qh->dummy; + struct list_head *entry, *tmp; + int stopped; + unsigned count = 0; + int do_status = 0; + u8 state; + u32 halt = HALT_BIT(ehci); + + /* verify params are valid */ + if (!qh || !kdburb) + return 0; + + if (unlikely (list_empty (&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe (entry, tmp, &qh->qtd_list) { + struct ehci_qtd *qtd; + struct urb *urb; + u32 token = 0; + + qtd = list_entry (entry, struct ehci_qtd, qtd_list); + urb = qtd->urb; + + if (urb != kdburb) + continue; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely (last->urb != urb)) { + ehci_urb_done (ehci, last->urb); + /* + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held and + * releases and then reacquires the lock. + * Thus, ehci_urb_done() returns with the lock + * held. We don't want to keep the lock + * held here, so release it. Check it first, + * just in case ehci_urb_done() is ever + * changed to not grab the lock. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock (&ehci->lock); + + count++; + } + ehci_qtd_free (ehci, last); + last = NULL; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb (); + token = hc32_to_cpu(ehci, qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + if ((token & QTD_STS_ACTIVE) == 0) { + + if ((token & QTD_STS_HALT) != 0) { + stopped = 1; + + /* magic dummy for some short reads; qh won't advance. + * that silicon quirk can kick in with this dummy too. + */ + } else if (IS_SHORT_READ (token) + && !(qtd->hw_alt_next + & EHCI_LIST_END(ehci))) { + stopped = 1; + goto halt; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely (!stopped + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { + break; + + } else { + stopped = 1; + + if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) + urb->status = -ESHUTDOWN; + + /* ignore active urbs unless some previous qtd + * for the urb faulted (including short read) or + * its urb was canceled. we may patch qh or qtds. + */ + if (likely (urb->status == -EINPROGRESS)) + continue; + + /* issue status after short control reads */ + if (unlikely (do_status != 0) + && QTD_PID (token) == 0 /* OUT */) { + do_status = 0; + continue; + } + + /* token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(ehci, qtd->qtd_dma) + == qh->hw_current) + token = hc32_to_cpu(ehci, qh->hw_token); + + /* force halt for unlinked or blocked qh, so we'll + * patch the qh later and so that completions can't + * activate it while we "know" it's stopped. + */ + if ((halt & qh->hw_token) == 0) { +halt: + qh->hw_token |= halt; + wmb (); + } + } + + /* remove it from the queue */ + spin_lock (&urb->lock); + qtd_copy_status (ehci, urb, qtd->length, token); + do_status = (urb->status == -EREMOTEIO) + && usb_pipecontrol (urb->pipe); + spin_unlock (&urb->lock); + + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry (qtd->qtd_list.prev, + struct ehci_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + list_del (&qtd->qtd_list); + last = qtd; + } + + /* last urb's completion might still need calling */ + if (likely (last != NULL)) { + ehci_urb_done (ehci, last->urb); + /* + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held and + * releases and then reacquires the lock. + * Thus, ehci_urb_done() returns with the lock + * held. We don't want to keep the lock + * held here, so release it. Check it first, just in + * case ehci_urb_done() is ever changed to not grab the lock. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock (&ehci->lock); + + count++; + ehci_qtd_free (ehci, last); + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); + break; + case QH_STATE_LINKED: + /* should be rare for periodic transfers, + * except maybe high bandwidth ... + */ + if ((cpu_to_hc32(ehci, QH_SMASK) + & qh->hw_info2) != 0) { + intr_deschedule (ehci, qh); + (void) qh_schedule (ehci, qh); + } else + unlink_async (ehci, qh); + break; + /* otherwise, unlink already started */ + } + } + + return count; +} + +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ // high bandwidth multiplier, as encoded in highspeed endpoint descriptors Index: linux/drivers/usb/host/ohci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-13 13:52:14.000000000 -0600 +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-13 14:13:50.996159433 -0600 @@ -857,10 +857,19 @@ struct ohci_hcd *ohci; struct ohci_regs * regs; - if (!urb) /* should not happen */ + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) return -1; ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ohci) + return -1; + + if (!HC_IS_RUNNING (ohci_to_hcd(ohci)->state)) + return -1; + regs = ohci->regs; /* if the urb is not currently in progress resubmit it */ Index: linux/kdb/kdb_io.c =================================================================== --- linux.orig/kdb/kdb_io.c 2007-11-13 13:52:14.000000000 -0600 +++ linux/kdb/kdb_io.c 2007-11-13 14:11:53.265345038 -0600 @@ -659,4 +659,18 @@ return; } +#ifdef CONFIG_KDB_USB + +int kdb_no_usb = 0; + +static int __init opt_kdbnousb(char *str) +{ + kdb_no_usb = 1; + return 0; +} + +early_param("kdbnousb", opt_kdbnousb); + +#endif + EXPORT_SYMBOL(kdb_read); --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From cybersrin@gmail.com Thu Nov 15 02:55:38 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 15 Nov 2007 02:55:43 -0800 (PST) Received: from nz-out-0506.google.com (nz-out-0506.google.com [64.233.162.229]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAFAtaIN006180 for ; Thu, 15 Nov 2007 02:55:38 -0800 Received: by nz-out-0506.google.com with SMTP id x3so429393nzd for ; Thu, 15 Nov 2007 02:55:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; bh=5vfTbkDdM8KdYWjS2qlFFEovNDl+ZW8Z01mzFFg04Go=; b=uP3ljzj5ZdsW9pGDJ3wVFQ2OKYckzz7k3MTPlmYxfaqgb73+NvMKHgAsJrFZfchRO3Na50SsUbZ2Xc5LGGgx4y5XzunsQ52W1KsvjRqZmqmRqxvCXEEXTkFG8+7HyThJSZADzHkDcJhnvVHUMeFMmmB0Wmqvd+eCbMaKJPSGMzk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=i47edMf1fqYbok8d1FxcLSVv8SruqhO6ojmY2kTrDVk7XCxOnNt4n4RT0GgqQGfJmN0po2MkcjXHck4qWpvC3JXbkXxl7VvvkrWxn6DrzIuJ3HiTo1+mtzpwQ6PQAcs5MXmwulttR3fx7QyWc9+QgjQwsnCBqUjDTgoLt6JGSgA= Received: by 10.142.113.17 with SMTP id l17mr50289wfc.1195122446069; Thu, 15 Nov 2007 02:27:26 -0800 (PST) Received: by 10.142.218.16 with HTTP; Thu, 15 Nov 2007 02:27:26 -0800 (PST) Message-ID: Date: Thu, 15 Nov 2007 15:57:26 +0530 From: "sri pnvs" To: kdb@oss.sgi.com Subject: KDB MIME-Version: 1.0 Content-type: text/plain Content-Transfer-Encoding: 8bit X-archive-position: 1279 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: cybersrin@gmail.com Precedence: bulk X-list: kdb Hello Experts, I am using KDB to debug the kernel modules. I am using redhat 2.6.9 kernel. As all of us know KDB is Assembly level debugger. After entering into KDB mode whole module is converted into Assmbly. It is very big code and very difficult to understand the assembly code for me as I don't have good knowledge in Assembly. Is there any solution to do the same stuff in C language.? Please let me know any workaround for this. I sincerely appreciate and thanks for your help on this. __________________ Thanks! Cyber --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From cybersrin@gmail.com Thu Nov 15 03:23:34 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 15 Nov 2007 03:23:42 -0800 (PST) Received: from nz-out-0506.google.com (nz-out-0506.google.com [64.233.162.232]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAFBNWCr010147 for ; Thu, 15 Nov 2007 03:23:33 -0800 Received: by nz-out-0506.google.com with SMTP id x3so434454nzd for ; Thu, 15 Nov 2007 03:23:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:in-reply-to:mime-version:content-type:references; bh=DoTWEgYw8J0pfcWgJtEfNmsblf6neTceRTfXH7wIj3k=; b=jYp+eZU5TvxucC5+85taSkJh6m4XL2tQ9Xkm6of9e3vKo+0bvpNBiHZKY/fNKQPGeXMgACm43rNmUfR/EGu1cmbA6AjvNVJTQrhnb2xAoHS4mqJyUrKn6SLYN2CowGCBdkbIjCFnuEsqXp4Z8NNCr92YGcA0V7A3bXeGWGeDfn0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:in-reply-to:mime-version:content-type:references; b=mcC5Cv9raUu+oQj9meG+ijuv+kNIbOXwEgfUX24S60tJJbIZc2roRsBNb4DXjSBqkzsoDIcE+OH6PxTOzX8vYkvA+pId4gkmFu0EXXK6fFtrw5VAZMz7XYsrX06KWsOJ5MkSL6OWgRECaXSuu87I4x8IkPwoT1qMV7Y0ObWG09Q= Received: by 10.142.177.7 with SMTP id z7mr54871wfe.1195122132117; Thu, 15 Nov 2007 02:22:12 -0800 (PST) Received: by 10.142.218.16 with HTTP; Thu, 15 Nov 2007 02:22:12 -0800 (PST) Message-ID: Date: Thu, 15 Nov 2007 15:52:12 +0530 From: "sri pnvs" To: kdb@oss.sgi.com Subject: Re: system hang when invoking the kdb In-Reply-To: MIME-Version: 1.0 Content-type: text/plain References: Content-Transfer-Encoding: 8bit X-archive-position: 1280 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: cybersrin@gmail.com Precedence: bulk X-list: kdb Hello Experts, I am using KDB to debug the kernel modules. I am using redhat 2.6.9 kernel. As all of us know KDB is Assembly level debugger. After entering into KDB mode whole module is converted into Assmbly. It is very big code and very difficult to understand the assembly code for me as I don't have good knowledge in Assembly. Is there any solution to do the same stuff in C language.? Please let me know any workaround for this. I sincerely appreciate and thanks for your help on this. __________________ Thanks! Cyber --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From slurndal@3leafnetworks.com Thu Nov 15 11:31:10 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 15 Nov 2007 11:31:15 -0800 (PST) Received: from pendragon.3leafnetworks.com (65-115-68-194.dia.static.qwest.net [65.115.68.194]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAFJV8Re021603 for ; Thu, 15 Nov 2007 11:31:09 -0800 Received: from pendragon.3leafnetworks.com (localhost.localdomain [127.0.0.1]) by pendragon.3leafnetworks.com (8.13.8/8.13.8) with ESMTP id lAFJ5lmL017567; Thu, 15 Nov 2007 11:05:47 -0800 Received: (from slurndal@localhost) by pendragon.3leafnetworks.com (8.13.8/8.13.8/Submit) id lAFJ5kGq017565; Thu, 15 Nov 2007 11:05:46 -0800 Date: Thu, 15 Nov 2007 11:05:46 -0800 From: Scott Lurndal To: sri pnvs Cc: kdb@oss.sgi.com Subject: Re: system hang when invoking the kdb Message-ID: <20071115190546.GG17077@pendragon.3leafnetworks.com> References: Mime-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.2i Content-Transfer-Encoding: 8bit X-archive-position: 1281 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: scott.lurndal@3leafsystems.com Precedence: bulk X-list: kdb On Thu, Nov 15, 2007 at 03:52:12PM +0530, sri pnvs wrote: > Hello Experts, > I am using KDB to debug the kernel modules. I am using redhat 2.6.9 kernel. > As all of us know KDB is Assembly level debugger. After entering into KDB > mode whole module is converted into Assmbly. It is very big code and very > difficult to understand the assembly code for me as I don't have good > knowledge in Assembly. > Is there any solution to do the same stuff in C language.? > Please let me know any workaround for this. > > I sincerely appreciate and thanks for your help on this. > There is no source-level capability with kdb. Learning assembly is a valuable skill, but if you don't desire to learn it, try kgdb instead. scott --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Thu Nov 15 11:41:37 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 15 Nov 2007 11:41:42 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAFJfYqa022668 for ; Thu, 15 Nov 2007 11:41:37 -0800 Received: from [134.15.0.122] (mtv-vpn-sw-corp-0-122.corp.sgi.com [134.15.0.122]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lAFJfdke025222; Thu, 15 Nov 2007 11:41:39 -0800 Message-ID: <473CA0F1.4050908@sgi.com> Date: Thu, 15 Nov 2007 11:41:37 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: KDB CC: Konstantin Baydarov Subject: [ANNOUNCE] kdb-v4.4-2.6.24-rc2-{common,ia64,x86}-3 available X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1282 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Hi all, I have ported the "New USB Keyboard interface for KDB" patch and the "KDB USB EHCI Support" patch from Aaron Young to 2.6.24-rc2. So now we have the patches against 2.6.23 (as Aaron posted) and also against 2.6.24-rc2. Konstantin, could you resubmit your UHCI patch against 2.6.24-rc2? Appreciated! Thanks, - jay --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Fri Nov 16 11:38:56 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 16 Nov 2007 11:39:02 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAGJctru022534 for ; Fri, 16 Nov 2007 11:38:56 -0800 Received: from [134.15.0.133] (mtv-vpn-sw-corp-0-133.corp.sgi.com [134.15.0.133]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lAGJd0ke031839; Fri, 16 Nov 2007 11:39:00 -0800 Message-ID: <473DF1D2.60304@sgi.com> Date: Fri, 16 Nov 2007 11:38:58 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: Jay Lan CC: KDB , Konstantin Baydarov Subject: Re: [ANNOUNCE] kdb-v4.4-2.6.24-rc2-{common,ia64,x86}-3 available References: <473CA0F1.4050908@sgi.com> In-Reply-To: <473CA0F1.4050908@sgi.com> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1283 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Jay Lan wrote: > Hi all, > > I have ported the "New USB Keyboard interface for KDB" patch > and the "KDB USB EHCI Support" patch from Aaron Young to > 2.6.24-rc2. Hi guys, I removed kdb-v4.4-2.6.24-rc2-{common,ia64,x86}-3 from oss.sgi.com ftp site for now. We need more testing on ehci support on x86_64 and i386. Pleae use the kdb-v4.4-2.6.24-rc2-{common,ia64,x86}-2 bits instead. Sorry about confusion. Regards, - jay > > So now we have the patches against 2.6.23 (as Aaron posted) and > also against 2.6.24-rc2. > > Konstantin, could you resubmit your UHCI patch against 2.6.24-rc2? > Appreciated! > > > Thanks, > - jay > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Tue Nov 20 06:49:31 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 20 Nov 2007 06:49:38 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAKEnU8D030258 for ; Tue, 20 Nov 2007 06:49:31 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAKEncK97628214 for ; Tue, 20 Nov 2007 06:49:38 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAKEnchB7662946 for kdb@oss.sgi.com; Tue, 20 Nov 2007 06:49:38 -0800 (PST) Date: Tue, 20 Nov 2007 06:49:38 -0800 (PST) From: Aaron Young Message-Id: <200711201449.lAKEnchB7662946@kluge.engr.sgi.com> To: kdb@oss.sgi.com Subject: [PATCH] RESEND - KDB USB EHCI Support X-archive-position: 1284 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb This patch is a resend to fix a locking problem found on X86_64 in linux/drivers/usb/host/ehci-q.c:qh_completions_kdb(). -- This patch adds support to KDB for USB keyboards attached via EHCI. This happens when USB keyboards are connected via a USB2.0 hub forcing the Linux kernel EHCI driver to take control instead of the "companion" OHCI or UHCI drivers. It also adds a new boot parameter, "kdbnousb", which when set will disable KDB from configuring and using USB keyboards. This may prove useful if someone experiences a problem with KDB and USB keyboards by allowing KDB to still be used via a serial attached keyboard. -- Patch is against 2.6.24-rc2 (and should be applied after kdb-v4.4-2.6.24-rc2-*-2 patch sets) Signed-off-by: Aaron Young (ayoung@sgi.com) Index: linux/arch/ia64/kdb/kdba_io.c =================================================================== --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-14 13:20:14.000000000 -0600 +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-14 16:49:28.490189077 -0600 @@ -44,6 +44,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -73,6 +75,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -107,6 +112,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -144,6 +152,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/arch/x86/kdb/kdba_io_32.c =================================================================== --- linux.orig/arch/x86/kdb/kdba_io_32.c 2007-11-14 13:20:15.000000000 -0600 +++ linux/arch/x86/kdb/kdba_io_32.c 2007-11-14 16:49:28.490189077 -0600 @@ -34,6 +34,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -63,6 +65,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -97,6 +102,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -134,6 +142,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/arch/x86/kdb/kdba_io_64.c =================================================================== --- linux.orig/arch/x86/kdb/kdba_io_64.c 2007-11-14 13:20:15.000000000 -0600 +++ linux/arch/x86/kdb/kdba_io_64.c 2007-11-14 16:49:28.490189077 -0600 @@ -34,6 +34,8 @@ #define KDB_USB_NUM_KEYBOARDS 8 struct kdb_usb_kbd_info kdb_usb_kbds[KDB_USB_NUM_KEYBOARDS]; +extern int kdb_no_usb; + static unsigned char kdb_usb_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, @@ -63,6 +65,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for a free index. If found, assign the keyboard to @@ -97,6 +102,9 @@ int i; int rc = -1; + if (kdb_no_usb) + return 0; + /* * Search through the array of KDB USB keyboards (kdb_usb_kbds) * looking for the index with the matching URB. If found, @@ -134,6 +142,9 @@ int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + + if (kdb_no_usb) + return -1; /* * Loop through all the USB keyboard(s) and return Index: linux/drivers/usb/host/ehci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-11-14 13:20:14.000000000 -0600 +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-14 16:49:28.490189077 -0600 @@ -933,8 +933,25 @@ int ehci_kdb_poll_char(struct urb *urb) { - /* routine not yet implemented */ - return -1; + struct ehci_hcd *ehci; + + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) + return -1; + + ehci = (struct ehci_hcd *) hcd_to_ehci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ehci) + return -1; + + if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) + return -1; + + if (qh_completions_kdb(ehci, urb->hcpriv, urb)) + return 0; + + return -1; } #endif /* CONFIG_KDB_USB */ Index: linux/drivers/usb/host/ehci-q.c =================================================================== --- linux.orig/drivers/usb/host/ehci-q.c 2007-11-14 13:18:35.000000000 -0600 +++ linux/drivers/usb/host/ehci-q.c 2007-11-16 08:57:23.008297555 -0600 @@ -444,6 +444,228 @@ return count; } +#ifdef CONFIG_KDB_USB +/* + * This routine is basically a copy of qh_completions() for use by KDB. + * It is modified to only work on qtds which are associated + * with 'kdburb'. Also, there are some fixups related to locking. + */ +unsigned +qh_completions_kdb(struct ehci_hcd *ehci, struct ehci_qh *qh, struct urb *kdburb) +{ + struct ehci_qtd *last = NULL, *end = qh->dummy; + struct list_head *entry, *tmp; + int last_status = -EINPROGRESS; + int stopped; + unsigned count = 0; + int do_status = 0; + u8 state; + u32 halt = HALT_BIT(ehci); + + /* verify params are valid */ + if (!qh || !kdburb) + return 0; + + if (unlikely (list_empty (&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe (entry, tmp, &qh->qtd_list) { + struct ehci_qtd *qtd; + struct urb *urb; + u32 token = 0; + int qtd_status; + + qtd = list_entry (entry, struct ehci_qtd, qtd_list); + urb = qtd->urb; + + if (urb != kdburb) + continue; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely (last->urb != urb)) { + /* + * Lock hackery here... + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held. + * So, lock it if it isn't already. + */ + if (!spin_is_locked(&ehci->lock)) + spin_lock(&ehci->lock); + + ehci_urb_done(ehci, last->urb, last_status); + + /* + * ehci_urb_done() releases and reacquires + * ehci->lock, so release it here. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock (&ehci->lock); + + count++; + } + ehci_qtd_free (ehci, last); + last = NULL; + last_status = -EINPROGRESS; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb (); + token = hc32_to_cpu(ehci, qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + if ((token & QTD_STS_ACTIVE) == 0) { + + if ((token & QTD_STS_HALT) != 0) { + stopped = 1; + + /* magic dummy for some short reads; qh won't advance. + * that silicon quirk can kick in with this dummy too. + */ + } else if (IS_SHORT_READ (token) + && !(qtd->hw_alt_next + & EHCI_LIST_END(ehci))) { + stopped = 1; + goto halt; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely (!stopped + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { + break; + + } else { + stopped = 1; + + if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) + last_status = -ESHUTDOWN; + + /* ignore active urbs unless some previous qtd + * for the urb faulted (including short read) or + * its urb was canceled. we may patch qh or qtds. + */ + if (likely(last_status == -EINPROGRESS && + !urb->unlinked)) + continue; + + /* issue status after short control reads */ + if (unlikely (do_status != 0) + && QTD_PID (token) == 0 /* OUT */) { + do_status = 0; + continue; + } + + /* token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(ehci, qtd->qtd_dma) + == qh->hw_current) + token = hc32_to_cpu(ehci, qh->hw_token); + + /* force halt for unlinked or blocked qh, so we'll + * patch the qh later and so that completions can't + * activate it while we "know" it's stopped. + */ + if ((halt & qh->hw_token) == 0) { +halt: + qh->hw_token |= halt; + wmb (); + } + } + + /* remove it from the queue */ + qtd_status = qtd_copy_status(ehci, urb, qtd->length, token); + if (unlikely(qtd_status == -EREMOTEIO)) { + do_status = (!urb->unlinked && + usb_pipecontrol(urb->pipe)); + qtd_status = 0; + } + if (likely(last_status == -EINPROGRESS)) + last_status = qtd_status; + + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry (qtd->qtd_list.prev, + struct ehci_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + list_del (&qtd->qtd_list); + last = qtd; + } + + /* last urb's completion might still need calling */ + if (likely (last != NULL)) { + /* + * Lock hackery here... + * ehci_urb_done() makes the assumption + * that it's called with ehci->lock held. + * So, lock it if it isn't already. + */ + if (!spin_is_locked(&ehci->lock)) + spin_lock(&ehci->lock); + + ehci_urb_done(ehci, last->urb, last_status); + + /* + * ehci_urb_done() releases and reacquires + * ehci->lock, so release it here. + */ + if (spin_is_locked(&ehci->lock)) + spin_unlock (&ehci->lock); + + count++; + ehci_qtd_free (ehci, last); + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(ehci, qh); + break; + case QH_STATE_LINKED: + /* should be rare for periodic transfers, + * except maybe high bandwidth ... + */ + if ((cpu_to_hc32(ehci, QH_SMASK) + & qh->hw_info2) != 0) { + intr_deschedule (ehci, qh); + (void) qh_schedule (ehci, qh); + } else + unlink_async (ehci, qh); + break; + /* otherwise, unlink already started */ + } + } + + return count; +} + +#endif /* CONFIG_KDB_USB */ + /*-------------------------------------------------------------------------*/ // high bandwidth multiplier, as encoded in highspeed endpoint descriptors Index: linux/drivers/usb/host/ohci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-14 13:20:13.000000000 -0600 +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-14 16:49:28.490189077 -0600 @@ -971,10 +971,19 @@ struct ohci_hcd *ohci; struct ohci_regs * regs; - if (!urb) /* should not happen */ - return -1; + /* just to make sure */ + if (!urb || !urb->dev || !urb->dev->bus) + return -1; ohci = (struct ohci_hcd *) hcd_to_ohci(bus_to_hcd(urb->dev->bus)); + + /* make sure */ + if (!ohci) + return -1; + + if (!HC_IS_RUNNING (ohci_to_hcd(ohci)->state)) + return -1; + regs = ohci->regs; /* if the urb is not currently in progress resubmit it */ Index: linux/kdb/kdb_io.c =================================================================== --- linux.orig/kdb/kdb_io.c 2007-11-14 13:20:13.000000000 -0600 +++ linux/kdb/kdb_io.c 2007-11-14 16:49:28.490189077 -0600 @@ -659,4 +659,18 @@ return; } +#ifdef CONFIG_KDB_USB + +int kdb_no_usb = 0; + +static int __init opt_kdbnousb(char *str) +{ + kdb_no_usb = 1; + return 0; +} + +early_param("kdbnousb", opt_kdbnousb); + +#endif + EXPORT_SYMBOL(kdb_read); --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Wed Nov 21 04:02:03 2007 Received: with ECARTIS (v1.0.0; list kdb); Wed, 21 Nov 2007 04:02:19 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lALC1uxQ010535 for ; Wed, 21 Nov 2007 04:02:01 -0800 Received: (qmail 3226 invoked from network); 21 Nov 2007 12:02:01 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.124) by mail.dev.rtsoft.ru with SMTP; 21 Nov 2007 12:02:01 -0000 Date: Wed, 21 Nov 2007 15:01:50 +0300 From: Konstantin Baydarov To: Aaron Young Cc: jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071121150150.01b5d24d@localhost.localdomain> In-Reply-To: <20071107171137.792d0304@localhost.localdomain> References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1285 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Wed, 7 Nov 2007 17:11:37 +0300 Konstantin Baydarov wrote: > On Mon, 5 Nov 2007 10:54:42 -0800 (PST) > Aaron Young wrote: > > > I've only dealt with OHCI driver code before, so I'm not qualified > > to review the UHCI specific code for you. As you say, it looks like > > a lot of your infastructure code introduces new globals > > (kdb_hcd_type) and uses kdb_usb_infos a lot - which is going away > > with my new implementation. > > > > Would it be possible for you to wait for my new kdb/usb > > infastructure code and re-implement your UHCI code against it at > > that time? I could attempt to take an in depth look at it at that > > time perhaps... > > > > Thanks, > > > > -Aaron > > Yes I'll intergrate UCHI code to the new KDB. > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to > unsubscribe. UCHI support integrated to kdb-v4.4-2.6.24-rc2. Tested on i386 UP PC. Changes in USB interface: - kdb_usb_uhci_keyboard_attach() to manage UHCI Keyboards - kdb_uhci_submit_urb() is called by kdb_usb_uhci_keyboard_attach(). UHCI KDB doesn't use HID urb, special urb with same parameters is used. - void (*kdb_completion)(struct urb *urb); was added to hc_driver structure to allow KDB UHCI driver reactivate KDB queue head. Known Issues of KDB driver: - Autoreply of pressed key doesn't work - When kernel enters KDB first pressed key doesn't appear on KDB console, because it's caught by UHCI kernel driver. - Keyboard hotplug wasn't tested. - Only 1 UHCI keyboard supported. Jay, it looks you are using spaces instead of tabs or your mail client replaces tabs with spaces, now(after USB patches) we have mixed code style. I think cleanup should be done. Signed-off-by: Konstantin Baydarov Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c @@ -25,6 +25,11 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +static struct uhci_qh *kdb_uhci_hid_qh; +#endif + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -292,6 +297,58 @@ static struct uhci_qh *uhci_alloc_qh(str return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1399,6 +1456,20 @@ static int uhci_urb_enqueue(struct usb_h if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (kdb_uhci_keyboard_urb(urb)){ + /* KDB urb will be enqued only once */ + kdb_uhci_hid_qh = NULL; + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); + if (!qh) + goto err_no_qh; + kdb_uhci_hid_qh = qh; + } else +#endif if (urb->ep->hcpriv) qh = urb->ep->hcpriv; else { @@ -1648,6 +1719,13 @@ static int uhci_advance_check(struct uhc int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if (qh == kdb_uhci_hid_qh){ + ret = 0; + goto done; + } +#endif if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1740,6 +1818,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if (qh == kdb_uhci_hid_qh) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1766,3 +1849,80 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +static int kdb_hid_event = 0; /* eq 1 when key was pressed/released */ + +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(void) +{ + struct urb_priv *urbp; + struct uhci_td *td; + struct uhci_qh *qh = kdb_uhci_hid_qh; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (struct urb *urb) +{ + if (!kdb_hid_event) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(); + kdb_hid_event = 0; +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static int uhci_check_kdb_uhci_qh(void) +{ + struct uhci_qh *qh = kdb_uhci_hid_qh; + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)){ + /* We're okay, the queue has advanced */ + kdb_hid_event = 1; + return 0; + } + return -1; +} +#endif Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c @@ -1045,8 +1045,17 @@ static int hid_probe(struct usb_interfac int ret; struct usbhid_device *usbhid = hid->driver_data; extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + extern int usb_hcd_check_uhci(struct usb_device *udev); + + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) + ret = kdb_usb_uhci_keyboard_attach(usbhid->urbin, usbhid->bufsize, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); + else + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + if (ret == -1) printk(": FAILED to register keyboard (%s) " Index: linux-2.6.24-rc2/include/linux/kdb.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdb.h +++ linux-2.6.24-rc2/include/linux/kdb.h @@ -143,9 +143,15 @@ extern void smp_kdb_stop(void); #include +extern int kdb_uhci_keyboard_urb(struct urb *urb); + extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); extern int kdb_usb_keyboard_detach(struct urb *urb); +extern int +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, + void *poll_func, void *compl_func); + #endif /* CONFIG_KDB_USB */ static inline Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,10 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include +#endif + /* * Version Information */ @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +static int +uhci_kdb_poll_char(struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return -1; + + return uhci_check_kdb_uhci_qh(); +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, + .kdb_completion = kdb_uhci_urb_complete, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c @@ -54,6 +54,93 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; +/* Check if URB is managed by KDB code */ +int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return 1; + } + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); + +/* Only 1 UHCI Keyboard supported */ +static int kdb_uhci_hid_initialized = 0; + +static inline void kdb_usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete_fn, + void *context, + int interval) +{ + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete_fn; + urb->context = context; + urb->interval = interval; + urb->start_frame = -1; +} + +static int kdb_uhci_submit_urb(int kbd_num, unsigned int usbhid_bufsize, struct urb *hid_inurb) +{ + dma_addr_t uhci_inbuf_dma; + + /* Only 1 UHCI Keyboard supported */ + if (kdb_uhci_hid_initialized) + return 1; + + if (!(kdb_usb_kbds[kbd_num].buffer = + usb_buffer_alloc(hid_inurb->dev, + usbhid_bufsize, GFP_ATOMIC, + &uhci_inbuf_dma))) + goto out; + + if (!(kdb_usb_kbds[kbd_num].urb = + usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + kdb_usb_fill_int_urb(kdb_usb_kbds[kbd_num].urb, + hid_inurb->dev, + hid_inurb->pipe, + kdb_usb_kbds[kbd_num].buffer, + hid_inurb->transfer_buffer_length, + hid_inurb->complete, + hid_inurb->context, + hid_inurb->interval + ); + + (kdb_usb_kbds[kbd_num].urb)->transfer_dma = uhci_inbuf_dma; + (kdb_usb_kbds[kbd_num].urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + if (usb_submit_urb(kdb_usb_kbds[kbd_num].urb, GFP_ATOMIC)) + goto out; + + kdb_uhci_hid_initialized = 1; +out: + if (kdb_uhci_hid_initialized) + return 0; + + /* Some Error Cleanup */ + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); + if (kdb_usb_kbds[kbd_num].buffer) + usb_buffer_free(hid_inurb->dev, + usbhid_bufsize, kdb_usb_kbds[kbd_num].buffer, + uhci_inbuf_dma); + + if (kdb_usb_kbds[kbd_num].urb) + usb_free_urb(kdb_usb_kbds[kbd_num].urb); + + return -1; +} + /* * kdb_usb_keyboard_attach() * Attach a USB keyboard to kdb. @@ -78,6 +165,7 @@ kdb_usb_keyboard_attach(struct urb *urb, kdb_usb_kbds[i].urb = urb; kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = NULL; rc = 0; /* success */ @@ -88,6 +176,44 @@ kdb_usb_keyboard_attach(struct urb *urb, } EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); +int +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, + void *poll_func, void *compl_func) +{ + int i; + int rc = -1; + + /* + * Search through the array of KDB USB keyboards (kdb_usb_kbds) + * looking for a free index. If found, assign the keyboard to + * the array index. + */ + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb) /* index is already assigned */ + continue; + + /* found a free array index */ + if (!(kdb_uhci_submit_urb(i, usbhid_bufsize, urb))){ + kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = compl_func; + } else { + /* Cleanup */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].urb_complete = NULL; + } + + rc = 0; /* success */ + + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL (kdb_usb_uhci_keyboard_attach); + /* * kdb_usb_keyboard_detach() * Detach a USB keyboard from kdb. @@ -135,6 +261,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int poll_ret, i2, j, max; + + ret = -1; /* * Loop through all the USB keyboard(s) and return @@ -148,20 +277,27 @@ get_usb_char(void) continue; /* Transfer char */ - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (poll_ret == -1) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; - keycode = kdb_usb_kbds[i].buffer[2]; + keycode = kdb_usb_kbds[i].buffer[max]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } - /* A normal key is pressed, decode it */ if(keycode) keycode = kdb_usb_keycode[keycode]; @@ -172,10 +308,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -184,31 +322,45 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; - + ret = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret = 8; + break; case 0x0F: /* TAB */ - return 9; + ret = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret = shift_map[keycode]; + break; } } } + /* Key was pressed, return keycode */ + break; } - /* no chars were returned from any of the USB keyboards */ + for(i2=0; i2<8; i2++){ + if (kdb_usb_kbds[i2].buffer) + for(j=0; j<8; j++){ + kdb_usb_kbds[i2].buffer[j] = (char)0; + } + } + + if (kdb_usb_kbds[i].urb_complete) + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); - return -1; + return ret; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/include/linux/kdbprivate.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h +++ linux-2.6.24-rc2/include/linux/kdbprivate.h @@ -489,6 +489,7 @@ struct kdb_usb_kbd_info { struct urb *urb; /* pointer to the URB */ unsigned char *buffer; /* pointer to the kbd char buffer */ int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ int caps_lock; /* state of the caps lock for this keyboard */ }; #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev return NULL; } EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); + +void * +usb_hcd_get_kdb_completion_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_completion); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); + +int +usb_hcd_check_uhci(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) + return 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); #endif /* CONFIG_KDB_USB */ /*-------------------------------------------------------------------------*/ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h @@ -213,6 +213,7 @@ struct hc_driver { #ifdef CONFIG_KDB_USB /* KDB poll function for this HC */ int (*kdb_poll_char)(struct urb *urb); + void (*kdb_completion)(struct urb *urb); #endif /* CONFIG_KDB_USB */ }; --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jidong.xiao@gmail.com Thu Nov 22 22:23:28 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 22 Nov 2007 22:23:35 -0800 (PST) Received: from nz-out-0506.google.com (nz-out-0506.google.com [64.233.162.226]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAN6NQV5014499 for ; Thu, 22 Nov 2007 22:23:27 -0800 Received: by nz-out-0506.google.com with SMTP id x3so2210995nzd for ; Thu, 22 Nov 2007 22:23:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=cuEBeAizGpf7CMRDa2buDbMqTbP0X/LNOQoab+edshE=; b=dDsKjxsBdzZJVgRzySQ9JAVdcSKIZIm50anr/g7+XsG2f0HjKYkbXQT9ZJIw1pXWFFnJn6ZsFAxOQQ/p15v3sPakAo/qAVgLURGLevgmfv1BpBvCWUxtNFl344evmSrQ68ynDnnXcOS5N2Uoms+PGfWBxhEcMFaI3CI+nrnlcuo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=Y8BHU+Ql9WWTk+ki1PaogVw7O8cRf8Tn13ADbKIaYzcTyeheZ+bRQ79V43mA8OI91Ckz+9ME0K+ZZLXPZq2pNwiGSTJklAwIm1kQR/vsBoJMkUnJ3c7JU49sLTColk61mpRlAIr/b/93deiNMO0wk/bv21XC1fVBkLM1oihywnA= Received: by 10.142.226.2 with SMTP id y2mr2537855wfg.1195799013723; Thu, 22 Nov 2007 22:23:33 -0800 (PST) Received: by 10.142.162.16 with HTTP; Thu, 22 Nov 2007 22:23:33 -0800 (PST) Message-ID: <4104961b0711222223m71859f3cy18a877a0265a6e2a@mail.gmail.com> Date: Fri, 23 Nov 2007 14:23:33 +0800 From: "jidong xiao" To: "Konstantin Baydarov" Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Cc: "Aaron Young" , "Jay Lan" , kdb@oss.sgi.com In-Reply-To: <20071121150150.01b5d24d@localhost.localdomain> MIME-Version: 1.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Disposition: inline References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> <20071121150150.01b5d24d@localhost.localdomain> X-archive-position: 1286 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jidong.xiao@gmail.com Precedence: bulk X-list: kdb On Nov 21, 2007 8:01 PM, Konstantin Baydarov wrote: > > On Wed, 7 Nov 2007 17:11:37 +0300 > Konstantin Baydarov wrote: > > > On Mon, 5 Nov 2007 10:54:42 -0800 (PST) > > Aaron Young wrote: > > > > > > > > Would it be possible for you to wait for my new kdb/usb > > > infastructure code and re-implement your UHCI code against it at > > > that time? I could attempt to take an in depth look at it at that > > > time perhaps... > > > > > > Thanks, > > > > > > -Aaron > > > > Yes I'll intergrate UCHI code to the new KDB. > > --------------------------- > > Use http://oss.sgi.com/ecartis to modify your settings or to > > unsubscribe. > > UCHI support integrated to kdb-v4.4-2.6.24-rc2. Tested on i386 UP PC. > > @@ -135,6 +261,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > /* > * Loop through all the USB keyboard(s) and return > @@ -148,20 +277,27 @@ get_usb_char(void) > continue; > > /* Transfer char */ > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > - if (ret == -1) /* error or no characters, try the next kbd */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > It seems once get_usb_char() is called,the poll_func i.e. uhci_kdb_poll_char might be invoked, but I am wondering who calls get_usb_char()?I didn't find any place where get_usb_call() is invoked. Regards Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Mon Nov 26 13:39:34 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 26 Nov 2007 13:39:41 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAQLdXA2006984 for ; Mon, 26 Nov 2007 13:39:34 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAQLdhK99051352; Mon, 26 Nov 2007 13:39:43 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAQLdgxG9156144; Mon, 26 Nov 2007 13:39:42 -0800 (PST) From: Aaron Young Message-Id: <200711262139.lAQLdgxG9156144@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: kbaidarov@ru.mvista.com (Konstantin Baydarov) Date: Mon, 26 Nov 2007 13:39:41 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <20071121150150.01b5d24d@localhost.localdomain> from "Konstantin Baydarov" at Nov 21, 2007 03:01:50 PM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1287 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb Konstantin, some comments: 1. You added some USB specific code to kdba_io_32.c, namely kdb_usb_fill_int_urb(), kdb_uhci_submit_urb(). Would it be better to put this USB code into the kernel uhci files (uhci-q.c, uhci-hcd.c or whatever) so kdb can remain unaware of USB specifics? Also, I think if you did it this way, then it would remove the need for the new interface routine kdb_usb_uhci_keyboard_attach(). You should be able to just call kdb_usb_keyboard_attach() after you create and submit the new URB from hid_probe(). Just add a new parameter to kdb_usb_keyboard_attach() for the complete_func and pass NULL for it for OHCI and EHCI. The USB infastructure is constantly being rewritten and structures/parameters changing around, so it would be best to keep those details over in the kernel and not in kdb IMO. 2. What is the limiting factor preventing multiple keyboards? Is it the use of the globals kdb_uhci_hid_qh and kdb_hid_event? Can this be fixed somehow? Can they be put into the per device kdb_usb_kbd_info struct maybe? 3. Why can't you use the HID URB? Locking? Using the HID URB seems to work fine for OHCI and EHCI. This is the reason that seems to cause so much complication in your code. Back in the 2.4 timeframe, Intel did a UHCI KDB implementation that used the HID URB. Perhaps it would be useful to dig up that old code and compare it? I can possibly pass that code on to you if you want... Also, does enqueing two URBs for the same device cause any problems (is it "legal")? 4. I think you'll need to add your new interfaces to kdba_io_64.c and arch/ia64/kdb/kdba_io.c. Otherwise, the USB modules will encounter link/build errors when they can't find kdb_usb_uhci_keyboard_attach() (and the other globals and such) on those builds/systems. It would be nice to have UHCI support on those archs too. 5. I already submitted another patch for EHCI support which will conflict with this one (kdba_io_32.c). Can you add your patch on top of that one? -Aaron > > On Wed, 7 Nov 2007 17:11:37 +0300 > Konstantin Baydarov wrote: > > > On Mon, 5 Nov 2007 10:54:42 -0800 (PST) > > Aaron Young wrote: > > > > > I've only dealt with OHCI driver code before, so I'm not qualified > > > to review the UHCI specific code for you. As you say, it looks like > > > a lot of your infastructure code introduces new globals > > > (kdb_hcd_type) and uses kdb_usb_infos a lot - which is going away > > > with my new implementation. > > > > > > Would it be possible for you to wait for my new kdb/usb > > > infastructure code and re-implement your UHCI code against it at > > > that time? I could attempt to take an in depth look at it at that > > > time perhaps... > > > > > > Thanks, > > > > > > -Aaron > > > > Yes I'll intergrate UCHI code to the new KDB. > > --------------------------- > > Use http://oss.sgi.com/ecartis to modify your settings or to > > unsubscribe. > > UCHI support integrated to kdb-v4.4-2.6.24-rc2. Tested on i386 UP PC. > > Changes in USB interface: > - kdb_usb_uhci_keyboard_attach() to manage UHCI Keyboards > - kdb_uhci_submit_urb() is called by kdb_usb_uhci_keyboard_attach(). UHCI KDB doesn't use HID urb, special urb with same parameters is used. > - void (*kdb_completion)(struct urb *urb); was added to hc_driver structure to allow KDB UHCI driver reactivate KDB queue head. > > Known Issues of KDB driver: > - Autoreply of pressed key doesn't work > - When kernel enters KDB first pressed key doesn't appear on KDB > console, because it's caught by UHCI kernel driver. > - Keyboard hotplug wasn't tested. > - Only 1 UHCI keyboard supported. > > Jay, it looks you are using spaces instead of tabs or your mail client replaces tabs with spaces, now(after USB patches) we have mixed code style. I think cleanup should be done. > > Signed-off-by: Konstantin Baydarov > > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > @@ -25,6 +25,11 @@ > * games with the FSBR code to make sure we get the correct order in all > * the cases. I don't think it's worth the effort > */ > +#ifdef CONFIG_KDB_USB > +/* KDB HID QH, managed by KDB code */ > +static struct uhci_qh *kdb_uhci_hid_qh; > +#endif > + > static void uhci_set_next_interrupt(struct uhci_hcd *uhci) > { > if (uhci->is_stopped) > @@ -292,6 +297,58 @@ static struct uhci_qh *uhci_alloc_qh(str > return qh; > } > > +#ifdef CONFIG_KDB_USB > +/* > + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv > + */ > +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, > + struct usb_device *udev, struct usb_host_endpoint *hep) > +{ > + dma_addr_t dma_handle; > + struct uhci_qh *qh; > + > + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); > + if (!qh) > + return NULL; > + > + memset(qh, 0, sizeof(*qh)); > + qh->dma_handle = dma_handle; > + > + qh->element = UHCI_PTR_TERM; > + qh->link = UHCI_PTR_TERM; > + > + INIT_LIST_HEAD(&qh->queue); > + INIT_LIST_HEAD(&qh->node); > + > + if (udev) { /* Normal QH */ > + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > + if (qh->type != USB_ENDPOINT_XFER_ISOC) { > + qh->dummy_td = uhci_alloc_td(uhci); > + if (!qh->dummy_td) { > + dma_pool_free(uhci->qh_pool, qh, dma_handle); > + return NULL; > + } > + } > + qh->state = QH_STATE_IDLE; > + qh->hep = hep; > + qh->udev = udev; > + > + if (qh->type == USB_ENDPOINT_XFER_INT || > + qh->type == USB_ENDPOINT_XFER_ISOC) > + qh->load = usb_calc_bus_time(udev->speed, > + usb_endpoint_dir_in(&hep->desc), > + qh->type == USB_ENDPOINT_XFER_ISOC, > + le16_to_cpu(hep->desc.wMaxPacketSize)) > + / 1000 + 1; > + > + } else { /* Skeleton QH */ > + qh->state = QH_STATE_ACTIVE; > + qh->type = -1; > + } > + return qh; > +} > +#endif > + > static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) > { > WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); > @@ -1399,6 +1456,20 @@ static int uhci_urb_enqueue(struct usb_h > if (!urbp) > goto done; > > +#ifdef CONFIG_KDB_USB > + /* Always allocate new QH for KDB URB. > + * KDB HQ will be managed by KDB poll code not by > + * UHCI HCD Driver. > + */ > + if (kdb_uhci_keyboard_urb(urb)){ > + /* KDB urb will be enqued only once */ > + kdb_uhci_hid_qh = NULL; > + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); > + if (!qh) > + goto err_no_qh; > + kdb_uhci_hid_qh = qh; > + } else > +#endif > if (urb->ep->hcpriv) > qh = urb->ep->hcpriv; > else { > @@ -1648,6 +1719,13 @@ static int uhci_advance_check(struct uhc > int ret = 1; > unsigned status; > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if (qh == kdb_uhci_hid_qh){ > + ret = 0; > + goto done; > + } > +#endif > if (qh->type == USB_ENDPOINT_XFER_ISOC) > goto done; > > @@ -1740,6 +1818,11 @@ rescan: > uhci->next_qh = list_entry(qh->node.next, > struct uhci_qh, node); > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if (qh == kdb_uhci_hid_qh) > + continue; > +#endif > if (uhci_advance_check(uhci, qh)) { > uhci_scan_qh(uhci, qh); > if (qh->state == QH_STATE_ACTIVE) { > @@ -1766,3 +1849,80 @@ rescan: > else > uhci_set_next_interrupt(uhci); > } > + > +#ifdef CONFIG_KDB_USB > +static int kdb_hid_event = 0; /* eq 1 when key was pressed/released */ > + > +/* > + * Activate KDB UHCI QH, called by KDB poll code. > + */ > +static void kdb_activate_uhci_qh(void) > +{ > + struct urb_priv *urbp; > + struct uhci_td *td; > + struct uhci_qh *qh = kdb_uhci_hid_qh; > + __le32 status, token; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + > + list_for_each_entry(td, &urbp->td_list, list){ > + status = td->status; > + token = td->token; > + barrier(); > + /* Clear Status and ActLen */ > + status &= cpu_to_le32(0xff000000); > + /* Make TD Active */ > + status |= cpu_to_le32(TD_CTRL_ACTIVE); > + /* Clear TD Interrupt */ > + status &= cpu_to_le32(~TD_CTRL_IOC); > + /* Toggle Data Sycronization Bit */ > + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) > + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); > + else > + token |= cpu_to_le32(TD_TOKEN_TOGGLE); > + > + td->token = token; > + td->status = status; > + barrier(); > + } > + /* Activate KDB UHCI Keyboard HID QH */ > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + qh->element = LINK_TO_TD(td); > + barrier(); > +} > + > +/* > + * Called when KDB finishes process key press/release event. > + */ > +static void > +kdb_uhci_urb_complete (struct urb *urb) > +{ > + if (!kdb_hid_event) > + return; > + > + /* Activate KDB TD */ > + kdb_activate_uhci_qh(); > + kdb_hid_event = 0; > +} > + > +/* > + * Check if state of KDB URB changed (key was pressed/released). > + */ > +static int uhci_check_kdb_uhci_qh(void) > +{ > + struct uhci_qh *qh = kdb_uhci_hid_qh; > + struct urb_priv *urbp = NULL; > + struct uhci_td *td; > + unsigned status; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + status = td_status(td); > + if (!(status & TD_CTRL_ACTIVE)){ > + /* We're okay, the queue has advanced */ > + kdb_hid_event = 1; > + return 0; > + } > + return -1; > +} > +#endif > Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c > +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > @@ -1045,8 +1045,17 @@ static int hid_probe(struct usb_interfac > int ret; > struct usbhid_device *usbhid = hid->driver_data; > extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + extern int usb_hcd_check_uhci(struct usb_device *udev); > + > + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) > + ret = kdb_usb_uhci_keyboard_attach(usbhid->urbin, usbhid->bufsize, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > + else > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + > > if (ret == -1) > printk(": FAILED to register keyboard (%s) " > Index: linux-2.6.24-rc2/include/linux/kdb.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdb.h > +++ linux-2.6.24-rc2/include/linux/kdb.h > @@ -143,9 +143,15 @@ extern void smp_kdb_stop(void); > > #include > > +extern int kdb_uhci_keyboard_urb(struct urb *urb); > + > extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > extern int kdb_usb_keyboard_detach(struct urb *urb); > > +extern int > +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, > + void *poll_func, void *compl_func); > + > #endif /* CONFIG_KDB_USB */ > > static inline > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > @@ -50,6 +50,10 @@ > #include "uhci-hcd.h" > #include "pci-quirks.h" > > +#ifdef CONFIG_KDB_USB > +#include > +#endif > + > /* > * Version Information > */ > @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h > return IRQ_HANDLED; > } > > +#ifdef CONFIG_KDB_USB > +static int > +uhci_kdb_poll_char(struct urb *urb) > +{ > + if (!urb) /* can happen if no keyboard attached */ > + return -1; > + > + return uhci_check_kdb_uhci_qh(); > +} > +#endif > + > /* > * Store the current frame number in uhci->frame_number if the controller > * is runnning. Expand from 11 bits (of which we use only 10) to a > @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive > > .hub_status_data = uhci_hub_status_data, > .hub_control = uhci_hub_control, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = uhci_kdb_poll_char, > + .kdb_completion = kdb_uhci_urb_complete, > +#endif > }; > > static const struct pci_device_id uhci_pci_ids[] = { { > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > @@ -54,6 +54,93 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > +/* Check if URB is managed by KDB code */ > +int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return 1; > + } > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > + > +/* Only 1 UHCI Keyboard supported */ > +static int kdb_uhci_hid_initialized = 0; > + > +static inline void kdb_usb_fill_int_urb (struct urb *urb, > + struct usb_device *dev, > + unsigned int pipe, > + void *transfer_buffer, > + int buffer_length, > + usb_complete_t complete_fn, > + void *context, > + int interval) > +{ > + urb->dev = dev; > + urb->pipe = pipe; > + urb->transfer_buffer = transfer_buffer; > + urb->transfer_buffer_length = buffer_length; > + urb->complete = complete_fn; > + urb->context = context; > + urb->interval = interval; > + urb->start_frame = -1; > +} > + > +static int kdb_uhci_submit_urb(int kbd_num, unsigned int usbhid_bufsize, struct urb *hid_inurb) > +{ > + dma_addr_t uhci_inbuf_dma; > + > + /* Only 1 UHCI Keyboard supported */ > + if (kdb_uhci_hid_initialized) > + return 1; > + > + if (!(kdb_usb_kbds[kbd_num].buffer = > + usb_buffer_alloc(hid_inurb->dev, > + usbhid_bufsize, GFP_ATOMIC, > + &uhci_inbuf_dma))) > + goto out; > + > + if (!(kdb_usb_kbds[kbd_num].urb = > + usb_alloc_urb(0, GFP_KERNEL))) > + goto out; > + > + kdb_usb_fill_int_urb(kdb_usb_kbds[kbd_num].urb, > + hid_inurb->dev, > + hid_inurb->pipe, > + kdb_usb_kbds[kbd_num].buffer, > + hid_inurb->transfer_buffer_length, > + hid_inurb->complete, > + hid_inurb->context, > + hid_inurb->interval > + ); > + > + (kdb_usb_kbds[kbd_num].urb)->transfer_dma = uhci_inbuf_dma; > + (kdb_usb_kbds[kbd_num].urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > + > + if (usb_submit_urb(kdb_usb_kbds[kbd_num].urb, GFP_ATOMIC)) > + goto out; > + > + kdb_uhci_hid_initialized = 1; > +out: > + if (kdb_uhci_hid_initialized) > + return 0; > + > + /* Some Error Cleanup */ > + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); > + if (kdb_usb_kbds[kbd_num].buffer) > + usb_buffer_free(hid_inurb->dev, > + usbhid_bufsize, kdb_usb_kbds[kbd_num].buffer, > + uhci_inbuf_dma); > + > + if (kdb_usb_kbds[kbd_num].urb) > + usb_free_urb(kdb_usb_kbds[kbd_num].urb); > + > + return -1; > +} > + > /* > * kdb_usb_keyboard_attach() > * Attach a USB keyboard to kdb. > @@ -78,6 +165,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > kdb_usb_kbds[i].urb = urb; > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = NULL; > > rc = 0; /* success */ > > @@ -88,6 +176,44 @@ kdb_usb_keyboard_attach(struct urb *urb, > } > EXPORT_SYMBOL_GPL (kdb_usb_keyboard_attach); > > +int > +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, > + void *poll_func, void *compl_func) > +{ > + int i; > + int rc = -1; > + > + /* > + * Search through the array of KDB USB keyboards (kdb_usb_kbds) > + * looking for a free index. If found, assign the keyboard to > + * the array index. > + */ > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb) /* index is already assigned */ > + continue; > + > + /* found a free array index */ > + if (!(kdb_uhci_submit_urb(i, usbhid_bufsize, urb))){ > + kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = compl_func; > + } else { > + /* Cleanup */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].urb_complete = NULL; > + } > + > + rc = 0; /* success */ > + > + break; > + } > + > + return rc; > +} > +EXPORT_SYMBOL_GPL (kdb_usb_uhci_keyboard_attach); > + > /* > * kdb_usb_keyboard_detach() > * Detach a USB keyboard from kdb. > @@ -135,6 +261,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > /* > * Loop through all the USB keyboard(s) and return > @@ -148,20 +277,27 @@ get_usb_char(void) > continue; > > /* Transfer char */ > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > - if (ret == -1) /* error or no characters, try the next kbd */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > - keycode = kdb_usb_kbds[i].buffer[2]; > + keycode = kdb_usb_kbds[i].buffer[max]; > kdb_usb_kbds[i].buffer[0] = (char)0; > kdb_usb_kbds[i].buffer[2] = (char)0; > > - if(kdb_usb_kbds[i].buffer[3]) { > - kdb_usb_kbds[i].buffer[3] = (char)0; > - continue; > - } > - > /* A normal key is pressed, decode it */ > if(keycode) > keycode = kdb_usb_keycode[keycode]; > @@ -172,10 +308,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -184,31 +322,45 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > - > + ret = 13; > + break; > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret = plain_map[keycode]; > + break; > } > else { > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > } > } > } > + /* Key was pressed, return keycode */ > + break; > } > > - /* no chars were returned from any of the USB keyboards */ > + for(i2=0; i2<8; i2++){ > + if (kdb_usb_kbds[i2].buffer) > + for(j=0; j<8; j++){ > + kdb_usb_kbds[i2].buffer[j] = (char)0; > + } > + } > + > + if (kdb_usb_kbds[i].urb_complete) > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > - return -1; > + return ret; > } > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/include/linux/kdbprivate.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h > +++ linux-2.6.24-rc2/include/linux/kdbprivate.h > @@ -489,6 +489,7 @@ struct kdb_usb_kbd_info { > struct urb *urb; /* pointer to the URB */ > unsigned char *buffer; /* pointer to the kbd char buffer */ > int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ > + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ > int caps_lock; /* state of the caps lock for this keyboard */ > }; > #endif /* CONFIG_KDB_USB */ > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c > @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev > return NULL; > } > EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > + > +void * > +usb_hcd_get_kdb_completion_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_completion); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); > + > +int > +usb_hcd_check_uhci(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) > + return 1; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); > #endif /* CONFIG_KDB_USB */ > > /*-------------------------------------------------------------------------*/ > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h > @@ -213,6 +213,7 @@ struct hc_driver { > #ifdef CONFIG_KDB_USB > /* KDB poll function for this HC */ > int (*kdb_poll_char)(struct urb *urb); > + void (*kdb_completion)(struct urb *urb); > #endif /* CONFIG_KDB_USB */ > }; > > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. > --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Mon Nov 26 13:50:33 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 26 Nov 2007 13:50:38 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAQLoWgl008544 for ; Mon, 26 Nov 2007 13:50:33 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAQLogK98870697; Mon, 26 Nov 2007 13:50:42 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAQLofCJ9184258; Mon, 26 Nov 2007 13:50:41 -0800 (PST) From: Aaron Young Message-Id: <200711262150.lAQLofCJ9184258@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: jidong.xiao@gmail.com (jidong xiao) Date: Mon, 26 Nov 2007 13:50:41 -0800 (PST) Cc: kbaidarov@ru.mvista.com (Konstantin Baydarov), ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <4104961b0711222223m71859f3cy18a877a0265a6e2a@mail.gmail.com> from "jidong xiao" at Nov 23, 2007 02:23:33 PM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1288 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb > > It seems once get_usb_char() is called,the poll_func i.e. > uhci_kdb_poll_char might be invoked, but I am wondering who calls > get_usb_char()?I didn't find any place where get_usb_call() is > invoked. > > Regards > Jason In the files arch/ia64/kdb/kdba_io.c arch/x86/kdb/kdba_io_32.c arch/x86/kdb/kdba_io_64.c poll_funcs[] is set like so: get_char_func poll_funcs[] = { #if defined(CONFIG_VT_CONSOLE) get_kbd_char, #endif #if defined(CONFIG_SERIAL_CONSOLE) get_serial_char, #endif #ifdef KDB_BLINK_LED blink_led, #endif #ifdef CONFIG_KDB_USB get_usb_char, <<<< here #endif NULL }; kdb/kdb_io.c:kdb_read() uses poll_funcs[] to get chars... -Aaron --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Mon Nov 26 14:45:32 2007 Received: with ECARTIS (v1.0.0; list kdb); Mon, 26 Nov 2007 14:45:38 -0800 (PST) Received: from buildserver.ru.mvista.com (rtsoft3.corbina.net [85.21.88.6] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAQMjSdK014829 for ; Mon, 26 Nov 2007 14:45:32 -0800 Received: from medved (unknown [10.150.0.9]) by buildserver.ru.mvista.com (Postfix) with ESMTP id 402BD8810; Tue, 27 Nov 2007 03:45:36 +0400 (SAMT) Date: Tue, 27 Nov 2007 01:45:41 +0300 From: Konstantin Baydarov To: Aaron Young Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071127014541.327ce2f1@medved> In-Reply-To: <200711262139.lAQLdgxG9156144@kluge.engr.sgi.com> References: <20071121150150.01b5d24d@localhost.localdomain> <200711262139.lAQLdgxG9156144@kluge.engr.sgi.com> X-Mailer: Claws Mail 2.9.1 (GTK+ 2.10.4; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1289 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Mon, 26 Nov 2007 13:39:41 -0800 (PST) Aaron Young wrote: > > > Konstantin, some comments: > > 3. Why can't you use the HID URB? Locking? Using the HID URB seems > to work fine for OHCI and EHCI. This is the reason that > seems to cause so much complication in your code. Back > in the 2.4 timeframe, Intel did a UHCI KDB implementation > that used the HID URB. Perhaps it would be useful to dig up that > old code and compare it? I can possibly pass that code on to you > if you want... > > Also, does enqueing two URBs for the same device cause any > problems (is it "legal")? > > > -Aaron > > I explained it earlier: http://oss.sgi.com/archives/kdb/2007-11/msg00003.html KDB Poll driver should not depend on USB kernel code because (in case when KDB driver uses the same code with kernel USB driver) if CPU0 executes kernel USB driver and, in the same time, CPU1 hits breakpoint, CPU0 would be frozen in kernel USB driver. USB spinlocks would be locked by CPU0, so KDB USB code couldn't get lock and deadlock would occur. Or, if we don't use lock, kernel USB driver data can't be corrupted. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Tue Nov 27 11:20:49 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 27 Nov 2007 11:20:56 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lARJKlaG017763 for ; Tue, 27 Nov 2007 11:20:49 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lARJKvK99352892; Tue, 27 Nov 2007 11:20:57 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lARJKuoh9310587; Tue, 27 Nov 2007 11:20:56 -0800 (PST) From: Aaron Young Message-Id: <200711271920.lARJKuoh9310587@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: kbaidarov@ru.mvista.com (Konstantin Baydarov) Date: Tue, 27 Nov 2007 11:20:56 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <20071127014541.327ce2f1@medved> from "Konstantin Baydarov" at Nov 27, 2007 01:45:41 AM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1290 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb > > On Mon, 26 Nov 2007 13:39:41 -0800 (PST) > Aaron Young wrote: > > > > > > > Konstantin, some comments: > > > > 3. Why can't you use the HID URB? Locking? Using the HID URB seems > > to work fine for OHCI and EHCI. This is the reason that > > seems to cause so much complication in your code. Back > > in the 2.4 timeframe, Intel did a UHCI KDB implementation > > that used the HID URB. Perhaps it would be useful to dig up that > > old code and compare it? I can possibly pass that code on to you > > if you want... > > > > Also, does enqueing two URBs for the same device cause any > > problems (is it "legal")? > > > > > > -Aaron > > > > > > I explained it earlier: > http://oss.sgi.com/archives/kdb/2007-11/msg00003.html > > KDB Poll driver should not depend on USB kernel code because (in case > when KDB driver uses the same code with kernel USB driver) if CPU0 > executes kernel USB driver and, in the same time, CPU1 hits breakpoint, > CPU0 would be frozen in kernel USB driver. USB spinlocks would be > locked by CPU0, so KDB USB code couldn't get lock and deadlock would > occur. Or, if we don't use lock, kernel USB driver data can't be > corrupted. Yes - you're right - it's *possible* to get into kdb while locks are held which, if timed just perfectly, could result in kdb crashing trying to walk lists, etc. This is also true of EHCI and OHCI (I think). I've never seen it happen, but it could in theory... I'm not sure it's worth it to rewrite all this code to cover this possibility, so what I might consider doing is just to check for the critical locks being held out of the poll functions and if so, give an error and punt (return -1) - i.e. the keyboard(s) for that HC will not be useable in this case. Much easier and probably sufficient for a debugger IMO. Jay, prepare for another patch for this! ;-) -Aaron --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Tue Nov 27 13:22:16 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 27 Nov 2007 13:22:21 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lARLMD4e010544 for ; Tue, 27 Nov 2007 13:22:15 -0800 Received: (qmail 22095 invoked from network); 27 Nov 2007 21:22:21 -0000 Received: from mail.dev.rtsoft.ru (HELO ?127.0.0.1?) (192.168.1.7) by mail.dev.rtsoft.ru with SMTP; 27 Nov 2007 21:22:21 -0000 Message-ID: <474C8A93.2030003@ru.mvista.com> Date: Wed, 28 Nov 2007 00:22:27 +0300 From: Konstantin Baydarov User-Agent: Thunderbird 1.5.0.13 (Windows/20070809) MIME-Version: 1.0 To: Aaron Young CC: Jay Lan , kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI References: <200711271920.lARJKuoh9310587@kluge.engr.sgi.com> In-Reply-To: <200711271920.lARJKuoh9310587@kluge.engr.sgi.com> Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1291 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb Aaron Young wrote: >> On Mon, 26 Nov 2007 13:39:41 -0800 (PST) >> Aaron Young wrote: >> >> >>> Konstantin, some comments: >>> >>> 3. Why can't you use the HID URB? Locking? Using the HID URB seems >>> to work fine for OHCI and EHCI. This is the reason that >>> seems to cause so much complication in your code. Back >>> in the 2.4 timeframe, Intel did a UHCI KDB implementation >>> that used the HID URB. Perhaps it would be useful to dig up that >>> old code and compare it? I can possibly pass that code on to you >>> if you want... >>> >>> Also, does enqueing two URBs for the same device cause any >>> problems (is it "legal")? >>> >>> >>> -Aaron >>> >>> >>> >> I explained it earlier: >> http://oss.sgi.com/archives/kdb/2007-11/msg00003.html >> >> KDB Poll driver should not depend on USB kernel code because (in case >> when KDB driver uses the same code with kernel USB driver) if CPU0 >> executes kernel USB driver and, in the same time, CPU1 hits breakpoint, >> CPU0 would be frozen in kernel USB driver. USB spinlocks would be >> locked by CPU0, so KDB USB code couldn't get lock and deadlock would >> occur. Or, if we don't use lock, kernel USB driver data can't be >> corrupted. >> > > Yes - you're right - it's *possible* to get into kdb while locks are > held which, if timed just perfectly, could result in kdb crashing trying > to walk lists, etc. This is also true of EHCI and OHCI (I think). > I've never seen it happen, but it could in theory... > > I'm not sure it's worth it to rewrite all this code to cover this possibility, > so what I might consider doing is just to check for the critical locks being > held out of the poll functions and if so, give an error and punt > (return -1) - i.e. the keyboard(s) for > that HC will not be useable in this case. Much easier > and probably sufficient for a debugger IMO. > > Jay, prepare for another patch for this! ;-) > > -Aaron > Aaron, I'm little bit confused . Are you going to integrate my UHCI code to KDB? --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Tue Nov 27 13:25:12 2007 Received: with ECARTIS (v1.0.0; list kdb); Tue, 27 Nov 2007 13:25:18 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lARLPBFO010840 for ; Tue, 27 Nov 2007 13:25:12 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lARLPLK99359230; Tue, 27 Nov 2007 13:25:22 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lARLPLWW9357559; Tue, 27 Nov 2007 13:25:21 -0800 (PST) From: Aaron Young Message-Id: <200711272125.lARLPLWW9357559@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: kbaidarov@ru.mvista.com (Konstantin Baydarov) Date: Tue, 27 Nov 2007 13:25:21 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <474C8A93.2030003@ru.mvista.com> from "Konstantin Baydarov" at Nov 28, 2007 12:22:27 AM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1292 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb > > Aaron Young wrote: > >> On Mon, 26 Nov 2007 13:39:41 -0800 (PST) > >> Aaron Young wrote: > >> > >> > >>> Konstantin, some comments: > >>> > >>> 3. Why can't you use the HID URB? Locking? Using the HID URB seems > >>> to work fine for OHCI and EHCI. This is the reason that > >>> seems to cause so much complication in your code. Back > >>> in the 2.4 timeframe, Intel did a UHCI KDB implementation > >>> that used the HID URB. Perhaps it would be useful to dig up that > >>> old code and compare it? I can possibly pass that code on to you > >>> if you want... > >>> > >>> Also, does enqueing two URBs for the same device cause any > >>> problems (is it "legal")? > >>> > >>> > >>> -Aaron > >>> > >>> > >>> > >> I explained it earlier: > >> http://oss.sgi.com/archives/kdb/2007-11/msg00003.html > >> > >> KDB Poll driver should not depend on USB kernel code because (in case > >> when KDB driver uses the same code with kernel USB driver) if CPU0 > >> executes kernel USB driver and, in the same time, CPU1 hits breakpoint, > >> CPU0 would be frozen in kernel USB driver. USB spinlocks would be > >> locked by CPU0, so KDB USB code couldn't get lock and deadlock would > >> occur. Or, if we don't use lock, kernel USB driver data can't be > >> corrupted. > >> > > > > Yes - you're right - it's *possible* to get into kdb while locks are > > held which, if timed just perfectly, could result in kdb crashing trying > > to walk lists, etc. This is also true of EHCI and OHCI (I think). > > I've never seen it happen, but it could in theory... > > > > I'm not sure it's worth it to rewrite all this code to cover this possibility, > > so what I might consider doing is just to check for the critical locks being > > held out of the poll functions and if so, give an error and punt > > (return -1) - i.e. the keyboard(s) for > > that HC will not be useable in this case. Much easier > > and probably sufficient for a debugger IMO. > > > > Jay, prepare for another patch for this! ;-) > > > > -Aaron > > > Aaron, I'm little bit confused . Are you going to integrate my UHCI > code to KDB? No - I was just talking about fixing OHCI and EHCI (in the manner I described above)... --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jidong.xiao@gmail.com Wed Nov 28 02:24:59 2007 Received: with ECARTIS (v1.0.0; list kdb); Wed, 28 Nov 2007 02:25:06 -0800 (PST) Received: from rv-out-0910.google.com (rv-out-0910.google.com [209.85.198.191]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lASAOuKt001324 for ; Wed, 28 Nov 2007 02:24:58 -0800 Received: by rv-out-0910.google.com with SMTP id k20so994872rvb for ; Wed, 28 Nov 2007 02:25:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=WY8goAsIeB343rosL9HiQp97T4GSgS67uUcx+f82x6w=; b=jm8++NiiXScer5agePafQ+p4ij63NUSJm83D8uDZaGWg9d30jqFrcbnPH2AKdZNUfDZIFljIlN2jF7/nE0MFXVvo/qIlhK6QeBP00Pn35H9uSZkMbQb82eQm6Y3Em6FaY76fHKUzCMpqU1zsw2a5nfqg1GOksr+82eE7LUPd9IM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=NyNm7Sy7YHyhm81j9ZPXFGFStCLi//3gAQW1uvJOH7ApjvEzQ071TLMYdPs00juM4xYYQYlUL5sb+ekN64M03cH842rnCgqXt6BsGLvmKyOj9vTMcRy2ZDOA4ufVZkcfO33oIYzRA4tGjQLdUa/IXHf7szKJv9IjkqJkgrxyL9Y= Received: by 10.141.78.14 with SMTP id f14mr2469306rvl.1196245504537; Wed, 28 Nov 2007 02:25:04 -0800 (PST) Received: by 10.140.174.9 with HTTP; Wed, 28 Nov 2007 02:25:04 -0800 (PST) Message-ID: <4104961b0711280225j112fffc3gaf1974733be0291f@mail.gmail.com> Date: Wed, 28 Nov 2007 18:25:04 +0800 From: "jidong xiao" To: "Konstantin Baydarov" Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Cc: "Aaron Young" , "Jay Lan" , kdb@oss.sgi.com In-Reply-To: <20071121150150.01b5d24d@localhost.localdomain> MIME-Version: 1.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Disposition: inline References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> <20071121150150.01b5d24d@localhost.localdomain> X-archive-position: 1293 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jidong.xiao@gmail.com Precedence: bulk X-list: kdb On Nov 21, 2007 8:01 PM, Konstantin Baydarov wrote: > > On Wed, 7 Nov 2007 17:11:37 +0300 > Konstantin Baydarov wrote: > > > On Mon, 5 Nov 2007 10:54:42 -0800 (PST) > > Aaron Young wrote: > > > > > I've only dealt with OHCI driver code before, so I'm not qualified > > > to review the UHCI specific code for you. As you say, it looks like > > > a lot of your infastructure code introduces new globals > > > (kdb_hcd_type) and uses kdb_usb_infos a lot - which is going away > > > with my new implementation. > > > > > > Would it be possible for you to wait for my new kdb/usb > > > infastructure code and re-implement your UHCI code against it at > > > that time? I could attempt to take an in depth look at it at that > > > time perhaps... > > > > > > Thanks, > > > > > > -Aaron > > > > Yes I'll intergrate UCHI code to the new KDB. > > --------------------------- > > Use http://oss.sgi.com/ecartis to modify your settings or to > > unsubscribe. > > UCHI support integrated to kdb-v4.4-2.6.24-rc2. Tested on i386 UP PC. > > Changes in USB interface: > - kdb_usb_uhci_keyboard_attach() to manage UHCI Keyboards > - kdb_uhci_submit_urb() is called by kdb_usb_uhci_keyboard_attach(). UHCI KDB doesn't use HID urb, special urb with same parameters is used. > - void (*kdb_completion)(struct urb *urb); was added to hc_driver structure to allow KDB UHCI driver reactivate KDB queue head. > > Known Issues of KDB driver: > - Autoreply of pressed key doesn't work > - When kernel enters KDB first pressed key doesn't appear on KDB > console, because it's caught by UHCI kernel driver. > - Keyboard hotplug wasn't tested. > - Only 1 UHCI keyboard supported. > > Jay, it looks you are using spaces instead of tabs or your mail client replaces tabs with spaces, now(after USB patches) we have mixed code style. I think cleanup should be done. > > Signed-off-by: Konstantin Baydarov > Has anyone else applied this patch?I am facing errors while compiling kernel with this patch. localhost:/usr/src/linux-2.6.24-rc2 # make ... ... ... CC arch/x86/lib/msr-on-cpu.o LD arch/x86/lib/built-in.o CC arch/x86/lib/bitops_32.o CC arch/x86/lib/delay_32.o AS arch/x86/lib/getuser_32.o CC arch/x86/lib/memcpy_32.o AS arch/x86/lib/putuser_32.o AS arch/x86/lib/semaphore_32.o CC arch/x86/lib/string_32.o CC arch/x86/lib/usercopy_32.o AR arch/x86/lib/lib.a GEN .version CHK include/linux/compile.h UPD include/linux/compile.h CC init/version.o LD init/built-in.o LD .tmp_vmlinux1 arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xee4): undefined reference to `usb_buffer_alloc' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xf01): undefined reference to `usb_alloc_urb' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xf70): undefined reference to `usb_submit_urb' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xfb3): undefined reference to `usb_buffer_free' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xfc5): undefined reference to `usb_free_urb' make: *** [.tmp_vmlinux1] Error 1 localhost:/usr/src/linux-2.6.24-rc2 # make CHK include/linux/version.h CHK include/linux/utsrelease.h CALL scripts/checksyscalls.sh CHK include/linux/compile.h GEN .version CHK include/linux/compile.h UPD include/linux/compile.h CC init/version.o LD init/built-in.o LD .tmp_vmlinux1 arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xee4): undefined reference to `usb_buffer_alloc' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xf01): undefined reference to `usb_alloc_urb' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xf70): undefined reference to `usb_submit_urb' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xfb3): undefined reference to `usb_buffer_free' arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': (.text+0xfc5): undefined reference to `usb_free_urb' make: *** [.tmp_vmlinux1] Error 1 This is quite strange, as I see usb_buffer_alloc is declared in ,and kdba_io_32.c includes which then includes . I am sure CONFIG_KDB_USB is enabled. So I am now frustrated with this issue. Regards Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Wed Nov 28 10:24:53 2007 Received: with ECARTIS (v1.0.0; list kdb); Wed, 28 Nov 2007 10:25:00 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lASIOpnB001373 for ; Wed, 28 Nov 2007 10:24:53 -0800 Received: from [150.166.8.78] (aware.engr.sgi.com [150.166.8.78]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lASIP0K99634596; Wed, 28 Nov 2007 10:25:01 -0800 (PST) Message-ID: <474DB2E7.9060607@sgi.com> Date: Wed, 28 Nov 2007 10:26:47 -0800 From: Jay Lan User-Agent: Thunderbird 2.0.0.6 (X11/20070801) MIME-Version: 1.0 To: jidong xiao CC: Konstantin Baydarov , Aaron Young , kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> <20071121150150.01b5d24d@localhost.localdomain> <4104961b0711280225j112fffc3gaf1974733be0291f@mail.gmail.com> In-Reply-To: <4104961b0711280225j112fffc3gaf1974733be0291f@mail.gmail.com> Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1294 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb jidong xiao wrote: > > Has anyone else applied this patch?I am facing errors while compiling > kernel with this patch. > > localhost:/usr/src/linux-2.6.24-rc2 # make > ... > ... > ... > CC arch/x86/lib/msr-on-cpu.o > LD arch/x86/lib/built-in.o > CC arch/x86/lib/bitops_32.o > CC arch/x86/lib/delay_32.o > AS arch/x86/lib/getuser_32.o > CC arch/x86/lib/memcpy_32.o > AS arch/x86/lib/putuser_32.o > AS arch/x86/lib/semaphore_32.o > CC arch/x86/lib/string_32.o > CC arch/x86/lib/usercopy_32.o > AR arch/x86/lib/lib.a > GEN .version > CHK include/linux/compile.h > UPD include/linux/compile.h > CC init/version.o > LD init/built-in.o > LD .tmp_vmlinux1 > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xee4): undefined reference to `usb_buffer_alloc' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xf01): undefined reference to `usb_alloc_urb' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xf70): undefined reference to `usb_submit_urb' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xfb3): undefined reference to `usb_buffer_free' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xfc5): undefined reference to `usb_free_urb' > make: *** [.tmp_vmlinux1] Error 1 > localhost:/usr/src/linux-2.6.24-rc2 # make > CHK include/linux/version.h > CHK include/linux/utsrelease.h > CALL scripts/checksyscalls.sh > CHK include/linux/compile.h > GEN .version > CHK include/linux/compile.h > UPD include/linux/compile.h > CC init/version.o > LD init/built-in.o > LD .tmp_vmlinux1 > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xee4): undefined reference to `usb_buffer_alloc' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xf01): undefined reference to `usb_alloc_urb' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xf70): undefined reference to `usb_submit_urb' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xfb3): undefined reference to `usb_buffer_free' > arch/x86/kdb/built-in.o: In function `kdb_usb_uhci_keyboard_attach': > (.text+0xfc5): undefined reference to `usb_free_urb' > make: *** [.tmp_vmlinux1] Error 1 > > This is quite strange, as I see usb_buffer_alloc is declared in > ,and kdba_io_32.c includes which then > includes . I am sure CONFIG_KDB_USB is enabled. So I am > now frustrated with this issue. I have not merged this patch yet, but those missing routines are defined in drivers/usb/core/{usb,urb}.c, and these routines will get compiled if CONFIG_USB is set. Is it possible that you used editor to enable CONFIG_KDB_USB? If you enable the config flag through 'make oldconfig', you need to have CONFIG_OHCI_HCD to enable CONFIG_KDB_USB. I think it then requires CONFIG_USB and then you should have had the missing routines. Thanks, - jay > > Regards > Jason > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Wed Nov 28 12:38:57 2007 Received: with ECARTIS (v1.0.0; list kdb); Wed, 28 Nov 2007 12:39:02 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lASKcu1i004446 for ; Wed, 28 Nov 2007 12:38:57 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lASKd8K99623363 for ; Wed, 28 Nov 2007 12:39:08 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lASKd7Pk7034217 for kdb@oss.sgi.com; Wed, 28 Nov 2007 12:39:07 -0800 (PST) Date: Wed, 28 Nov 2007 12:39:07 -0800 (PST) From: Aaron Young Message-Id: <200711282039.lASKd7Pk7034217@kluge.engr.sgi.com> To: kdb@oss.sgi.com Subject: [PATCH] KDB USB HCD deadlock fix X-archive-position: 1295 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb This patch fixes a timing hole and possible kdb deadlock in the event that KDB is entered while the USB HCD (Host Controller Driver) is busy processing URBs and holding the HCD lock. We now check for the lock being held out of the OHCI and EHCI poll functions and if so, return -EBUSY. In the event of an -EBUSY return, kdb will output a NOTICE message and the keyboard will not be used for input. It is anticpated that the timing hole is small and therefore *very* rarely happen. It remains a project for someone in the future if they want to attempt to fix this in another way (perhaps by using a independent KDB URB?)... Patch shjould be applied on top of my previous ehci support patch. Signed-off-by: Aaron Young (ayoung@sgi.com) Index: linux/arch/ia64/kdb/kdba_io.c =================================================================== --- linux.orig/arch/ia64/kdb/kdba_io.c 2007-11-28 14:09:31.000000000 -0600 +++ linux/arch/ia64/kdb/kdba_io.c 2007-11-28 14:16:07.715948546 -0600 @@ -169,7 +169,14 @@ /* Transfer char */ ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + + if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY) + kdb_printf("NOTICE: USB HCD driver BUSY. " + "USB keyboard has been disabled.\n"); + + kdb_usb_kbds[i].poll_ret = ret; + + if (ret < 0) /* error or no characters, try the next kbd */ continue; spec = kdb_usb_kbds[i].buffer[0]; Index: linux/arch/x86/kdb/kdba_io_32.c =================================================================== --- linux.orig/arch/x86/kdb/kdba_io_32.c 2007-11-28 14:09:31.000000000 -0600 +++ linux/arch/x86/kdb/kdba_io_32.c 2007-11-28 14:16:43.512398556 -0600 @@ -159,7 +159,14 @@ /* Transfer char */ ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + + if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY) + kdb_printf("NOTICE: USB HCD driver BUSY. " + "USB keyboard has been disabled.\n"); + + kdb_usb_kbds[i].poll_ret = ret; + + if (ret < 0) /* error or no characters, try the next kbd */ continue; spec = kdb_usb_kbds[i].buffer[0]; Index: linux/arch/x86/kdb/kdba_io_64.c =================================================================== --- linux.orig/arch/x86/kdb/kdba_io_64.c 2007-11-28 14:09:31.000000000 -0600 +++ linux/arch/x86/kdb/kdba_io_64.c 2007-11-28 14:16:52.521518496 -0600 @@ -159,7 +159,14 @@ /* Transfer char */ ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + + if (ret == -EBUSY && kdb_usb_kbds[i].poll_ret != -EBUSY) + kdb_printf("NOTICE: USB HCD driver BUSY. " + "USB keyboard has been disabled.\n"); + + kdb_usb_kbds[i].poll_ret = ret; + + if (ret < 0) /* error or no characters, try the next kbd */ continue; spec = kdb_usb_kbds[i].buffer[0]; Index: linux/drivers/usb/host/ehci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ehci-hcd.c 2007-11-28 14:09:31.000000000 -0600 +++ linux/drivers/usb/host/ehci-hcd.c 2007-11-28 14:17:07.455374932 -0600 @@ -948,6 +948,20 @@ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) return -1; + /* + * If ehci->lock is held coming into this routine, it could + * mean KDB was entered while the HC driver was in the midst + * of processing URBs. Therefore it could be dangerous to + * processes URBs from this poll routine. And, we can't wait on + * the lock since we are in KDB and kernel threads (including the + * one holding the lock) are suspended. + * So, we punt and return an error. Keyboards attached to this + * HC will not be useable from KDB at this time. + */ + if (spin_is_locked(&ehci->lock)) + return -EBUSY; + + /* processes the URB */ if (qh_completions_kdb(ehci, urb->hcpriv, urb)) return 0; Index: linux/drivers/usb/host/ohci-hcd.c =================================================================== --- linux.orig/drivers/usb/host/ohci-hcd.c 2007-11-28 14:09:31.000000000 -0600 +++ linux/drivers/usb/host/ohci-hcd.c 2007-11-28 14:17:21.049064751 -0600 @@ -984,6 +984,19 @@ if (!HC_IS_RUNNING (ohci_to_hcd(ohci)->state)) return -1; + /* + * If ohci->lock is held coming into this routine, it could + * mean KDB was entered while the HC driver was in the midst + * of processing URBs. Therefore it could be dangerous to + * processes URBs from this poll routine. And, we can't wait on + * the lock since we are in KDB and kernel threads (including the + * one holding the lock) are suspended. + * So, we punt and return an error. Keyboards attached to this + * HC will not be useable from KDB at this time. + */ + if (spin_is_locked(&ohci->lock)) + return -EBUSY; + regs = ohci->regs; /* if the urb is not currently in progress resubmit it */ Index: linux/include/linux/kdbprivate.h =================================================================== --- linux.orig/include/linux/kdbprivate.h 2007-11-28 14:09:28.000000000 -0600 +++ linux/include/linux/kdbprivate.h 2007-11-28 14:17:29.446108569 -0600 @@ -489,6 +489,7 @@ struct urb *urb; /* pointer to the URB */ unsigned char *buffer; /* pointer to the kbd char buffer */ int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int poll_ret; /* return val from poll_func */ int caps_lock; /* state of the caps lock for this keyboard */ }; #endif /* CONFIG_KDB_USB */ --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Thu Nov 29 07:27:54 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 29 Nov 2007 07:28:01 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lATFRo08015097 for ; Thu, 29 Nov 2007 07:27:53 -0800 Received: (qmail 3476 invoked from network); 29 Nov 2007 15:27:55 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.195) by mail.dev.rtsoft.ru with SMTP; 29 Nov 2007 15:27:55 -0000 Date: Thu, 29 Nov 2007 18:27:48 +0300 From: Konstantin Baydarov To: "jidong xiao" Cc: "Jay Lan" , "Aaron Young" , kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071129182748.34451518@localhost.localdomain> In-Reply-To: <4104961b0711282247k76cb0df4o12b75634e7dedce3@mail.gmail.com> References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> <20071121150150.01b5d24d@localhost.localdomain> <4104961b0711280225j112fffc3gaf1974733be0291f@mail.gmail.com> <474DB2E7.9060607@sgi.com> <4104961b0711282247k76cb0df4o12b75634e7dedce3@mail.gmail.com> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1296 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Thu, 29 Nov 2007 14:47:03 +0800 "jidong xiao" wrote: > On Nov 29, 2007 2:26 AM, Jay Lan wrote: > Well, According to Konstantin's email that saying:"UHCI support > integrated to kdb-v4.4-2.6.24-rc2. Tested on i386 UP PC." So What was > doing is: > 1. Downloaded kernel 2.6.24-rc2. > 2. Downloaded kdb-v4.4-2.6.24-rc2-common-2 plus > kdb-v4.4-2.6.24-rc2-x86-2, and then applied these two patches. > 3. Applied Konstantin's UHCI patch. > 4. make menuconfig&make > > And now I am stuck on step 4 as mentioned before. > Here I also attached my .config file, please see the attachment.my > machine is i386. > The most strange thing is,those missing routines are also used by > other usb modules, such as usb-storage, however, usb-storage can be > successfully compiled and if I comment out CONFIG_KDB_USB, the > compiling can totally pass. > > See following which is generated by `make modules_install` after the > kernel compiling without enabling CONFIG_KDB_USB. > > localhost:~ # ls -lR /lib/modules/2.6.24-rc2/kernel/drivers/usb/ > /lib/modules/2.6.24-rc2/kernel/drivers/usb/: > total 0 > drwxr-xr-x 2 root root 80 Nov 25 07:17 core > drwxr-xr-x 2 root root 144 Nov 25 07:17 host > drwxr-xr-x 2 root root 80 Nov 25 07:17 mon > drwxr-xr-x 2 root root 80 Nov 25 07:17 storage > > /lib/modules/2.6.24-rc2/kernel/drivers/usb/core: > total 160 > -rw-r--r-- 1 root root 160232 Nov 25 07:17 usbcore.ko > > /lib/modules/2.6.24-rc2/kernel/drivers/usb/host: > total 132 > -rw-r--r-- 1 root root 49302 Nov 25 07:17 ehci-hcd.ko > -rw-r--r-- 1 root root 40352 Nov 25 07:17 ohci-hcd.ko > -rw-r--r-- 1 root root 39020 Nov 25 07:17 uhci-hcd.ko > > /lib/modules/2.6.24-rc2/kernel/drivers/usb/mon: > total 24 > -rw-r--r-- 1 root root 23219 Nov 25 07:17 usbmon.ko > > /lib/modules/2.6.24-rc2/kernel/drivers/usb/storage: > total 72 > -rw-r--r-- 1 root root 71200 Nov 25 07:17 usb-storage.ko > > Regards > Jason Jason, you "USB support" should be compiled in kernel not as module: Location: -> Device Drivers -> USB support (USB_SUPPORT [=y]) I didn't know that "USB support" can be compiled as module, I'll fix it. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jidong.xiao@gmail.com Thu Nov 29 20:21:48 2007 Received: with ECARTIS (v1.0.0; list kdb); Thu, 29 Nov 2007 20:21:55 -0800 (PST) Received: from el-out-1112.google.com (el-out-1112.google.com [209.85.162.177]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAU4LiIv008983 for ; Thu, 29 Nov 2007 20:21:48 -0800 Received: by el-out-1112.google.com with SMTP id y26so1086374ele for ; Thu, 29 Nov 2007 20:21:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=1T+n44D+soyqUMrHM/wSaCBGdpIZVPIvTPx6dN9yKzg=; b=ryAbc1eA02Uq9x0uuyR1s/HpRjMw9LL0CCDXlQVzNdXBX+6eHrdjJda+pHegmwU5r/HXjq3rgwd/4BL/wMdM9F8UQ34JaLy7UGdzkjnwKJUEZ4iIKU9zq2S6GLJz9s4BLMyy/kTNiFACxxGzZoms0smvzb1O9/HAqKjjsA7YoNY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=jcaKkdOpVzhPHD346/BPg0a9t8JuGIbCWnomrduHR+Kzo2xyNsYj4gVLRik6vTRYhtTkN5q2hmYMqYck8EY1i0alXTw3lMhspVOaSkGU3vAc28lDvwmsT28opwzcl6QgYAu9fZy75Z67uEq8fHqSEh3YWKP5IFrqjHPpC9DiGLU= Received: by 10.142.142.16 with SMTP id p16mr2340428wfd.1196396512944; Thu, 29 Nov 2007 20:21:52 -0800 (PST) Received: by 10.142.162.16 with HTTP; Thu, 29 Nov 2007 20:21:52 -0800 (PST) Message-ID: <4104961b0711292021g54146ae2ncbb469ec86d0595e@mail.gmail.com> Date: Fri, 30 Nov 2007 12:21:52 +0800 From: "jidong xiao" To: "Konstantin Baydarov" Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Cc: "Jay Lan" , "Aaron Young" , kdb@oss.sgi.com In-Reply-To: <20071129182748.34451518@localhost.localdomain> MIME-Version: 1.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Disposition: inline References: <20071105211716.14674612@medved> <200711051854.lA5Isg1n4205041@kluge.engr.sgi.com> <20071107171137.792d0304@localhost.localdomain> <20071121150150.01b5d24d@localhost.localdomain> <4104961b0711280225j112fffc3gaf1974733be0291f@mail.gmail.com> <474DB2E7.9060607@sgi.com> <4104961b0711282247k76cb0df4o12b75634e7dedce3@mail.gmail.com> <20071129182748.34451518@localhost.localdomain> X-archive-position: 1297 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jidong.xiao@gmail.com Precedence: bulk X-list: kdb On Nov 29, 2007 11:27 PM, Konstantin Baydarov wrote: > On Thu, 29 Nov 2007 14:47:03 +0800 > > Jason, you "USB support" should be compiled in kernel not as module: > Location: > -> Device Drivers > -> USB support (USB_SUPPORT [=y]) > > I didn't know that "USB support" can be compiled as module, I'll fix it. > Well, there are two options, CONFIG_USB and CONFIG_USB_SUPPORT. And my settings were: # # USB HID Boot Protocol drivers # # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=m CONFIG_USB_DEBUG=y I guess what you meant should be CONFIG_USB, you meant this option should be compiled into kernel rather than as a module,right? Then I tried to change CONFIG_USB from "m" to "y", and indeed the compiling now passed.However mostly people compile CONFIG_USB as a module, i.e. usbcore. Anyway, thanks. I will test against your patches next step. Regards Jason --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Fri Nov 30 05:59:51 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 06:00:00 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lAUDxlkY021565 for ; Fri, 30 Nov 2007 05:59:49 -0800 Received: (qmail 19475 invoked from network); 30 Nov 2007 13:59:55 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.195) by mail.dev.rtsoft.ru with SMTP; 30 Nov 2007 13:59:55 -0000 Date: Fri, 30 Nov 2007 16:59:53 +0300 From: Konstantin Baydarov To: Aaron Young Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071130165953.209a0265@localhost.localdomain> In-Reply-To: <200711262139.lAQLdgxG9156144@kluge.engr.sgi.com> References: <20071121150150.01b5d24d@localhost.localdomain> <200711262139.lAQLdgxG9156144@kluge.engr.sgi.com> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1298 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Mon, 26 Nov 2007 13:39:41 -0800 (PST) Aaron Young wrote: > > > Konstantin, some comments: > > 1. You added some USB specific code to kdba_io_32.c, namely > kdb_usb_fill_int_urb(), kdb_uhci_submit_urb(). > > Would it be better to put this USB code into the kernel uhci > files (uhci-q.c, uhci-hcd.c or whatever) so kdb can remain unaware > of USB specifics? > Also, I think if you did it this way, then it would remove the need > for the new interface routine kdb_usb_uhci_keyboard_attach(). You > should be able to just call kdb_usb_keyboard_attach() after you > create and submit the new URB from hid_probe(). Just add > a new parameter to kdb_usb_keyboard_attach() for the > complete_func and pass NULL for it for OHCI and EHCI. > > The USB infastructure is constantly being rewritten and > structures/parameters changing around, so it would be best to keep > those details over in the kernel and not in kdb IMO. > - Got rid from kdb_usb_uhci_keyboard_attach() - Added "poll_func" argument to kdb_usb_keyboard_attach() - Moved kdb_usb_fill_int_urb() and kdb_uhci_submit_urb() to hid-core.c. That fixes compilation errors (problem reported by jidong xiao) when USB subsystem is compiled as kernel module. > 2. What is the limiting factor preventing multiple keyboards? Is it > the use of the globals kdb_uhci_hid_qh and kdb_hid_event? Can this > be fixed somehow? Can they be put into the per device > kdb_usb_kbd_info struct maybe? > - Moved kdb_uhci_hid_qh and hid_event to kdb_usb_kbd_info. Now multiple UHCI keyboards are supported. > 4. I think you'll need to add your new interfaces to kdba_io_64.c > and arch/ia64/kdb/kdba_io.c. Otherwise, the USB modules will > encounter link/build errors when they can't find > kdb_usb_uhci_keyboard_attach() (and the other globals and such) on > those builds/systems. It would be nice to have UHCI support on those > archs too. > - Added x86_64 part. > 5. I already submitted another patch for EHCI support which will > conflict with this one (kdba_io_32.c). Can you add your patch on > top of that one? - Done. > > > -Aaron > Patch against kernel 2.6.24-rc2. Was tested on i386 kernel with 2 UHCI keyboards. Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c @@ -25,6 +25,18 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +extern int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh); +extern int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); +extern struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); +extern int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); +extern int kdb_uhci_keyboard_get_hid_event(struct urb *urb); +extern int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); +extern int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh); +#endif + + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -292,6 +304,58 @@ static struct uhci_qh *uhci_alloc_qh(str return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1399,6 +1463,20 @@ static int uhci_urb_enqueue(struct usb_h if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (kdb_uhci_keyboard_urb(urb) != -1){ + /* KDB urb will be enqued only once */ + kdb_uhci_keyboard_set_qh(urb, NULL); + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); + if (!qh) + goto err_no_qh; + kdb_uhci_keyboard_set_qh(urb, qh); + } else +#endif if (urb->ep->hcpriv) qh = urb->ep->hcpriv; else { @@ -1648,6 +1726,13 @@ static int uhci_advance_check(struct uhc int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1){ + ret = 0; + goto done; + } +#endif if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1740,6 +1825,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1766,3 +1856,76 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp; + struct uhci_td *td; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (struct urb *urb) +{ + if (!kdb_uhci_keyboard_get_hid_event(urb)) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); + kdb_uhci_keyboard_set_hid_event(urb, 0); +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)){ + /* We're okay, the queue has advanced */ + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); + return 0; + } + return -1; +} +#endif Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c @@ -969,6 +969,86 @@ static void hid_disconnect(struct usb_in hid_free_device(hid); } +#ifdef CONFIG_KDB_USB +/* Only 1 UHCI Keyboard supported */ +static inline void kdb_usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete_fn, + void *context, + int interval) +{ + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete_fn; + urb->context = context; + urb->interval = interval; + urb->start_frame = -1; +} + +static int kdb_uhci_submit_urb(struct usb_interface *intf, unsigned int usbhid_bufsize, struct urb *hid_inurb) +{ + struct urb *kdb_urb = NULL; + unsigned char *kdb_buffer; + dma_addr_t uhci_inbuf_dma; + int ret = -1; + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, + usbhid_bufsize, GFP_ATOMIC, + &uhci_inbuf_dma))) + goto out; + + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + kdb_usb_fill_int_urb(kdb_urb, + hid_inurb->dev, + hid_inurb->pipe, + kdb_buffer, + hid_inurb->transfer_buffer_length, + hid_inurb->complete, + hid_inurb->context, + hid_inurb->interval + ); + + (kdb_urb)->transfer_dma = uhci_inbuf_dma; + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + ret = kdb_usb_keyboard_attach(kdb_urb, kdb_buffer, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); + + if (ret){ + kdb_uhci_keyboard_clear(kdb_urb); + goto out; + } + + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)) + goto out; + + ret = 0; + return ret; +out: + /* Some Error Cleanup */ + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); + if (kdb_buffer) + usb_buffer_free(hid_inurb->dev, + usbhid_bufsize, kdb_buffer, + uhci_inbuf_dma); + + if (kdb_urb) + usb_free_urb(kdb_urb); + + return ret; +} +#endif + static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct hid_device *hid; @@ -1045,8 +1125,15 @@ static int hid_probe(struct usb_interfac int ret; struct usbhid_device *usbhid = hid->driver_data; extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + extern int usb_hcd_check_uhci(struct usb_device *udev); + + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) + ret = kdb_uhci_submit_urb(intf, usbhid->bufsize, usbhid->urbin); + else + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); if (ret == -1) printk(": FAILED to register keyboard (%s) " Index: linux-2.6.24-rc2/include/linux/kdb.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdb.h +++ linux-2.6.24-rc2/include/linux/kdb.h @@ -143,9 +143,17 @@ extern void smp_kdb_stop(void); #include -extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); +extern int kdb_uhci_keyboard_urb(struct urb *urb); +extern int kdb_uhci_keyboard_clear(struct urb *urb); +extern int kdb_usb_keyboard_alloc(void); + +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func, void *compl_func); extern int kdb_usb_keyboard_detach(struct urb *urb); +extern int +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, + void *poll_func, void *compl_func); + #endif /* CONFIG_KDB_USB */ static inline Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,10 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include +#endif + /* * Version Information */ @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +static int +uhci_kdb_poll_char(struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return -1; + + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, + .kdb_completion = kdb_uhci_urb_complete, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; +/* Check if URB is managed by KDB code */ +int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); + +/* Check if UHCI QH is managed by KDB code */ +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); + +/* Clear keyboar entry */ +int kdb_uhci_keyboard_clear(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].urb_complete = NULL; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); + +/* Set UHCI QH using URB pointer */ +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].qh = qh; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); + +/* Get UHCI QH using URB pointer */ +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + return kdb_usb_kbds[i].qh; + } + + return NULL; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); + +/* Set UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); + +/* Get UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + return kdb_usb_kbds[i].kdb_hid_event; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); + +/* Set UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); + +/* Get UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return kdb_usb_kbds[i].kdb_hid_event; + } + + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); + /* * kdb_usb_keyboard_attach() * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func) { int i; int rc = -1; @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, kdb_usb_kbds[i].urb = urb; kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = compl_func; rc = 0; /* success */ @@ -142,6 +277,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int poll_ret, i2, j, max; + + ret = -1; if (kdb_no_usb) return -1; @@ -158,20 +296,27 @@ get_usb_char(void) continue; /* Transfer char */ - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (poll_ret == -1) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; - keycode = kdb_usb_kbds[i].buffer[2]; + keycode = kdb_usb_kbds[i].buffer[max]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } - /* A normal key is pressed, decode it */ if(keycode) keycode = kdb_usb_keycode[keycode]; @@ -182,10 +327,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -194,31 +341,45 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; - + ret = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret = 8; + break; case 0x0F: /* TAB */ - return 9; + ret = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret = shift_map[keycode]; + break; } } } + /* Key was pressed, return keycode */ + break; } - /* no chars were returned from any of the USB keyboards */ + for(i2=0; i2<8; i2++){ + if (kdb_usb_kbds[i2].buffer) + for(j=0; j<8; j++){ + kdb_usb_kbds[i2].buffer[j] = (char)0; + } + } + + if (kdb_usb_kbds[i].urb_complete) + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); - return -1; + return ret; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_64.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; +/* Check if URB is managed by KDB code */ +int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); + +/* Check if UHCI QH is managed by KDB code */ +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); + +/* Clear keyboar entry */ +int kdb_uhci_keyboard_clear(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].urb_complete = NULL; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); + +/* Set UHCI QH using URB pointer */ +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].qh = qh; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); + +/* Get UHCI QH using URB pointer */ +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + return kdb_usb_kbds[i].qh; + } + + return NULL; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); + +/* Set UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); + +/* Get UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + /* found a free array index */ + return kdb_usb_kbds[i].kdb_hid_event; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); + +/* Set UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); + +/* Get UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return kdb_usb_kbds[i].kdb_hid_event; + } + + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); + /* * kdb_usb_keyboard_attach() * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func) { int i; int rc = -1; @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, kdb_usb_kbds[i].urb = urb; kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = compl_func; rc = 0; /* success */ @@ -142,6 +277,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int poll_ret, i2, j, max; + + ret = -1; if (kdb_no_usb) return -1; @@ -158,20 +296,27 @@ get_usb_char(void) continue; /* Transfer char */ - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); - if (ret == -1) /* error or no characters, try the next kbd */ + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); + if (poll_ret == -1) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; - keycode = kdb_usb_kbds[i].buffer[2]; + keycode = kdb_usb_kbds[i].buffer[max]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } - /* A normal key is pressed, decode it */ if(keycode) keycode = kdb_usb_keycode[keycode]; @@ -182,10 +327,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -194,31 +341,45 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; - + ret = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret = 8; + break; case 0x0F: /* TAB */ - return 9; + ret = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret = shift_map[keycode]; + break; } } } + /* Key was pressed, return keycode */ + break; } - /* no chars were returned from any of the USB keyboards */ + for(i2=0; i2<8; i2++){ + if (kdb_usb_kbds[i2].buffer) + for(j=0; j<8; j++){ + kdb_usb_kbds[i2].buffer[j] = (char)0; + } + } + + if (kdb_usb_kbds[i].urb_complete) + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); - return -1; + return ret; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/include/linux/kdbprivate.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h +++ linux-2.6.24-rc2/include/linux/kdbprivate.h @@ -489,7 +489,10 @@ struct kdb_usb_kbd_info { struct urb *urb; /* pointer to the URB */ unsigned char *buffer; /* pointer to the kbd char buffer */ int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ int caps_lock; /* state of the caps lock for this keyboard */ + struct uhci_qh *qh; + int kdb_hid_event; }; #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev return NULL; } EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); + +void * +usb_hcd_get_kdb_completion_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_completion); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); + +int +usb_hcd_check_uhci(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) + return 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); #endif /* CONFIG_KDB_USB */ /*-------------------------------------------------------------------------*/ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h @@ -213,6 +213,7 @@ struct hc_driver { #ifdef CONFIG_KDB_USB /* KDB poll function for this HC */ int (*kdb_poll_char)(struct urb *urb); + void (*kdb_completion)(struct urb *urb); #endif /* CONFIG_KDB_USB */ }; --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 30 07:52:51 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 07:53:00 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUFqoLt001630 for ; Fri, 30 Nov 2007 07:52:51 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAUFqxK910059543; Fri, 30 Nov 2007 07:53:00 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAUFqxdA9993872; Fri, 30 Nov 2007 07:52:59 -0800 (PST) From: Aaron Young Message-Id: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: kbaidarov@ru.mvista.com (Konstantin Baydarov) Date: Fri, 30 Nov 2007 07:52:59 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <20071130165953.209a0265@localhost.localdomain> from "Konstantin Baydarov" at Nov 30, 2007 04:59:53 PM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1299 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb Looking better! More comments: 1. I don't understand the need for the call to kdb_uhci_keyboard_clear(). It's only called if kdb_usb_keyboard_attach() fails and in that case we didn't add the urb to kdb_usb_kbds[]. So, I don't see the need to clear it out of kdb_usb_kbds[]... (I'm probably missing something here). 2. I probably would have made kdb_uhci_submit_urb() return the newly created kdb_urb (extra arg) on success and not call kdb_usb_keyboard_attach() directly from within. Then you can just make a single call to kdb_usb_keyboard_attach() for all three cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not a *BIG* deal... 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise it will result in compile errors on ia64. i.e. kdb_usb_keyboard_attach() will have a number of args mismatch and all the routines you added to kdba_io_32.c and kdba_io_64.c will not be there. 4. You have the comment "/* found a free array index */" in several of the new kdba_io*.c routines when it really means you found a "match". 5. I just submitted another patch on Wed (Nov. 28th). That will conflict with this one again. Sorry - should be my last patch. Does hotplug/hotunplug of the keyboards work? Does it correctly remove the KDB URBs on hotunplug? Thanks, -Aaron > > On Mon, 26 Nov 2007 13:39:41 -0800 (PST) > Aaron Young wrote: > > > > > > > Konstantin, some comments: > > > > 1. You added some USB specific code to kdba_io_32.c, namely > > kdb_usb_fill_int_urb(), kdb_uhci_submit_urb(). > > > > Would it be better to put this USB code into the kernel uhci > > files (uhci-q.c, uhci-hcd.c or whatever) so kdb can remain unaware > > of USB specifics? > > Also, I think if you did it this way, then it would remove the need > > for the new interface routine kdb_usb_uhci_keyboard_attach(). You > > should be able to just call kdb_usb_keyboard_attach() after you > > create and submit the new URB from hid_probe(). Just add > > a new parameter to kdb_usb_keyboard_attach() for the > > complete_func and pass NULL for it for OHCI and EHCI. > > > > The USB infastructure is constantly being rewritten and > > structures/parameters changing around, so it would be best to keep > > those details over in the kernel and not in kdb IMO. > > > - Got rid from kdb_usb_uhci_keyboard_attach() > - Added "poll_func" argument to kdb_usb_keyboard_attach() > - Moved kdb_usb_fill_int_urb() and kdb_uhci_submit_urb() to hid-core.c. That fixes compilation errors (problem reported by jidong xiao) when USB subsystem is compiled as kernel module. > > > 2. What is the limiting factor preventing multiple keyboards? Is it > > the use of the globals kdb_uhci_hid_qh and kdb_hid_event? Can this > > be fixed somehow? Can they be put into the per device > > kdb_usb_kbd_info struct maybe? > > > - Moved kdb_uhci_hid_qh and hid_event to kdb_usb_kbd_info. Now multiple UHCI keyboards are supported. > > > 4. I think you'll need to add your new interfaces to kdba_io_64.c > > and arch/ia64/kdb/kdba_io.c. Otherwise, the USB modules will > > encounter link/build errors when they can't find > > kdb_usb_uhci_keyboard_attach() (and the other globals and such) on > > those builds/systems. It would be nice to have UHCI support on those > > archs too. > > > - Added x86_64 part. > > > 5. I already submitted another patch for EHCI support which will > > conflict with this one (kdba_io_32.c). Can you add your patch on > > top of that one? > - Done. > > > > > > > -Aaron > > > > Patch against kernel 2.6.24-rc2. Was tested on i386 kernel with 2 UHCI keyboards. > > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > @@ -25,6 +25,18 @@ > * games with the FSBR code to make sure we get the correct order in all > * the cases. I don't think it's worth the effort > */ > +#ifdef CONFIG_KDB_USB > +/* KDB HID QH, managed by KDB code */ > +extern int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh); > +extern int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); > +extern struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); > +extern int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); > +extern int kdb_uhci_keyboard_get_hid_event(struct urb *urb); > +extern int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); > +extern int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh); > +#endif > + > + > static void uhci_set_next_interrupt(struct uhci_hcd *uhci) > { > if (uhci->is_stopped) > @@ -292,6 +304,58 @@ static struct uhci_qh *uhci_alloc_qh(str > return qh; > } > > +#ifdef CONFIG_KDB_USB > +/* > + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv > + */ > +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, > + struct usb_device *udev, struct usb_host_endpoint *hep) > +{ > + dma_addr_t dma_handle; > + struct uhci_qh *qh; > + > + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); > + if (!qh) > + return NULL; > + > + memset(qh, 0, sizeof(*qh)); > + qh->dma_handle = dma_handle; > + > + qh->element = UHCI_PTR_TERM; > + qh->link = UHCI_PTR_TERM; > + > + INIT_LIST_HEAD(&qh->queue); > + INIT_LIST_HEAD(&qh->node); > + > + if (udev) { /* Normal QH */ > + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > + if (qh->type != USB_ENDPOINT_XFER_ISOC) { > + qh->dummy_td = uhci_alloc_td(uhci); > + if (!qh->dummy_td) { > + dma_pool_free(uhci->qh_pool, qh, dma_handle); > + return NULL; > + } > + } > + qh->state = QH_STATE_IDLE; > + qh->hep = hep; > + qh->udev = udev; > + > + if (qh->type == USB_ENDPOINT_XFER_INT || > + qh->type == USB_ENDPOINT_XFER_ISOC) > + qh->load = usb_calc_bus_time(udev->speed, > + usb_endpoint_dir_in(&hep->desc), > + qh->type == USB_ENDPOINT_XFER_ISOC, > + le16_to_cpu(hep->desc.wMaxPacketSize)) > + / 1000 + 1; > + > + } else { /* Skeleton QH */ > + qh->state = QH_STATE_ACTIVE; > + qh->type = -1; > + } > + return qh; > +} > +#endif > + > static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) > { > WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); > @@ -1399,6 +1463,20 @@ static int uhci_urb_enqueue(struct usb_h > if (!urbp) > goto done; > > +#ifdef CONFIG_KDB_USB > + /* Always allocate new QH for KDB URB. > + * KDB HQ will be managed by KDB poll code not by > + * UHCI HCD Driver. > + */ > + if (kdb_uhci_keyboard_urb(urb) != -1){ > + /* KDB urb will be enqued only once */ > + kdb_uhci_keyboard_set_qh(urb, NULL); > + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); > + if (!qh) > + goto err_no_qh; > + kdb_uhci_keyboard_set_qh(urb, qh); > + } else > +#endif > if (urb->ep->hcpriv) > qh = urb->ep->hcpriv; > else { > @@ -1648,6 +1726,13 @@ static int uhci_advance_check(struct uhc > int ret = 1; > unsigned status; > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1){ > + ret = 0; > + goto done; > + } > +#endif > if (qh->type == USB_ENDPOINT_XFER_ISOC) > goto done; > > @@ -1740,6 +1825,11 @@ rescan: > uhci->next_qh = list_entry(qh->node.next, > struct uhci_qh, node); > > +#ifdef CONFIG_KDB_USB > + /* Don't manage KDB QH */ > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1) > + continue; > +#endif > if (uhci_advance_check(uhci, qh)) { > uhci_scan_qh(uhci, qh); > if (qh->state == QH_STATE_ACTIVE) { > @@ -1766,3 +1856,76 @@ rescan: > else > uhci_set_next_interrupt(uhci); > } > + > +#ifdef CONFIG_KDB_USB > +/* > + * Activate KDB UHCI QH, called by KDB poll code. > + */ > +static void kdb_activate_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp; > + struct uhci_td *td; > + __le32 status, token; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + > + list_for_each_entry(td, &urbp->td_list, list){ > + status = td->status; > + token = td->token; > + barrier(); > + /* Clear Status and ActLen */ > + status &= cpu_to_le32(0xff000000); > + /* Make TD Active */ > + status |= cpu_to_le32(TD_CTRL_ACTIVE); > + /* Clear TD Interrupt */ > + status &= cpu_to_le32(~TD_CTRL_IOC); > + /* Toggle Data Sycronization Bit */ > + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) > + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); > + else > + token |= cpu_to_le32(TD_TOKEN_TOGGLE); > + > + td->token = token; > + td->status = status; > + barrier(); > + } > + /* Activate KDB UHCI Keyboard HID QH */ > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + qh->element = LINK_TO_TD(td); > + barrier(); > +} > + > +/* > + * Called when KDB finishes process key press/release event. > + */ > +static void > +kdb_uhci_urb_complete (struct urb *urb) > +{ > + if (!kdb_uhci_keyboard_get_hid_event(urb)) > + return; > + > + /* Activate KDB TD */ > + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > + kdb_uhci_keyboard_set_hid_event(urb, 0); > +} > + > +/* > + * Check if state of KDB URB changed (key was pressed/released). > + */ > +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) > +{ > + struct urb_priv *urbp = NULL; > + struct uhci_td *td; > + unsigned status; > + > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > + status = td_status(td); > + if (!(status & TD_CTRL_ACTIVE)){ > + /* We're okay, the queue has advanced */ > + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); > + return 0; > + } > + return -1; > +} > +#endif > Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c > +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > @@ -969,6 +969,86 @@ static void hid_disconnect(struct usb_in > hid_free_device(hid); > } > > +#ifdef CONFIG_KDB_USB > +/* Only 1 UHCI Keyboard supported */ > +static inline void kdb_usb_fill_int_urb (struct urb *urb, > + struct usb_device *dev, > + unsigned int pipe, > + void *transfer_buffer, > + int buffer_length, > + usb_complete_t complete_fn, > + void *context, > + int interval) > +{ > + urb->dev = dev; > + urb->pipe = pipe; > + urb->transfer_buffer = transfer_buffer; > + urb->transfer_buffer_length = buffer_length; > + urb->complete = complete_fn; > + urb->context = context; > + urb->interval = interval; > + urb->start_frame = -1; > +} > + > +static int kdb_uhci_submit_urb(struct usb_interface *intf, unsigned int usbhid_bufsize, struct urb *hid_inurb) > +{ > + struct urb *kdb_urb = NULL; > + unsigned char *kdb_buffer; > + dma_addr_t uhci_inbuf_dma; > + int ret = -1; > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + > + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, > + usbhid_bufsize, GFP_ATOMIC, > + &uhci_inbuf_dma))) > + goto out; > + > + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) > + goto out; > + > + kdb_usb_fill_int_urb(kdb_urb, > + hid_inurb->dev, > + hid_inurb->pipe, > + kdb_buffer, > + hid_inurb->transfer_buffer_length, > + hid_inurb->complete, > + hid_inurb->context, > + hid_inurb->interval > + ); > + > + (kdb_urb)->transfer_dma = uhci_inbuf_dma; > + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > + > + ret = kdb_usb_keyboard_attach(kdb_urb, kdb_buffer, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > + > + if (ret){ > + kdb_uhci_keyboard_clear(kdb_urb); > + goto out; > + } > + > + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)) > + goto out; > + > + ret = 0; > + return ret; > +out: > + /* Some Error Cleanup */ > + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); > + if (kdb_buffer) > + usb_buffer_free(hid_inurb->dev, > + usbhid_bufsize, kdb_buffer, > + uhci_inbuf_dma); > + > + if (kdb_urb) > + usb_free_urb(kdb_urb); > + > + return ret; > +} > +#endif > + > static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) > { > struct hid_device *hid; > @@ -1045,8 +1125,15 @@ static int hid_probe(struct usb_interfac > int ret; > struct usbhid_device *usbhid = hid->driver_data; > extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > + extern int usb_hcd_check_uhci(struct usb_device *udev); > + > + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) > + ret = kdb_uhci_submit_urb(intf, usbhid->bufsize, usbhid->urbin); > + else > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > > if (ret == -1) > printk(": FAILED to register keyboard (%s) " > Index: linux-2.6.24-rc2/include/linux/kdb.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdb.h > +++ linux-2.6.24-rc2/include/linux/kdb.h > @@ -143,9 +143,17 @@ extern void smp_kdb_stop(void); > > #include > > -extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > +extern int kdb_uhci_keyboard_urb(struct urb *urb); > +extern int kdb_uhci_keyboard_clear(struct urb *urb); > +extern int kdb_usb_keyboard_alloc(void); > + > +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func, void *compl_func); > extern int kdb_usb_keyboard_detach(struct urb *urb); > > +extern int > +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, > + void *poll_func, void *compl_func); > + > #endif /* CONFIG_KDB_USB */ > > static inline > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > @@ -50,6 +50,10 @@ > #include "uhci-hcd.h" > #include "pci-quirks.h" > > +#ifdef CONFIG_KDB_USB > +#include > +#endif > + > /* > * Version Information > */ > @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h > return IRQ_HANDLED; > } > > +#ifdef CONFIG_KDB_USB > +static int > +uhci_kdb_poll_char(struct urb *urb) > +{ > + if (!urb) /* can happen if no keyboard attached */ > + return -1; > + > + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > +} > +#endif > + > /* > * Store the current frame number in uhci->frame_number if the controller > * is runnning. Expand from 11 bits (of which we use only 10) to a > @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive > > .hub_status_data = uhci_hub_status_data, > .hub_control = uhci_hub_control, > +#ifdef CONFIG_KDB_USB > + .kdb_poll_char = uhci_kdb_poll_char, > + .kdb_completion = kdb_uhci_urb_complete, > +#endif > }; > > static const struct pci_device_id uhci_pci_ids[] = { { > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > +/* Check if URB is managed by KDB code */ > +int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > + > +/* Check if UHCI QH is managed by KDB code */ > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > + > +/* Clear keyboar entry */ > +int kdb_uhci_keyboard_clear(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].urb_complete = NULL; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > + > +/* Set UHCI QH using URB pointer */ > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].qh = qh; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > + > +/* Get UHCI QH using URB pointer */ > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].qh; > + } > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > + > +/* Set UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > + > +/* Get UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > + > +/* Set UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + return i; > + } > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > + > +/* Get UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > + > /* > * kdb_usb_keyboard_attach() > * Attach a USB keyboard to kdb. > */ > int > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > + void *poll_func, void *compl_func) > { > int i; > int rc = -1; > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > kdb_usb_kbds[i].urb = urb; > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = compl_func; > > rc = 0; /* success */ > > @@ -142,6 +277,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > if (kdb_no_usb) > return -1; > @@ -158,20 +296,27 @@ get_usb_char(void) > continue; > > /* Transfer char */ > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > - if (ret == -1) /* error or no characters, try the next kbd */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > - keycode = kdb_usb_kbds[i].buffer[2]; > + keycode = kdb_usb_kbds[i].buffer[max]; > kdb_usb_kbds[i].buffer[0] = (char)0; > kdb_usb_kbds[i].buffer[2] = (char)0; > > - if(kdb_usb_kbds[i].buffer[3]) { > - kdb_usb_kbds[i].buffer[3] = (char)0; > - continue; > - } > - > /* A normal key is pressed, decode it */ > if(keycode) > keycode = kdb_usb_keycode[keycode]; > @@ -182,10 +327,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -194,31 +341,45 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > - > + ret = 13; > + break; > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret = plain_map[keycode]; > + break; > } > else { > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > } > } > } > + /* Key was pressed, return keycode */ > + break; > } > > - /* no chars were returned from any of the USB keyboards */ > + for(i2=0; i2<8; i2++){ > + if (kdb_usb_kbds[i2].buffer) > + for(j=0; j<8; j++){ > + kdb_usb_kbds[i2].buffer[j] = (char)0; > + } > + } > + > + if (kdb_usb_kbds[i].urb_complete) > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > - return -1; > + return ret; > } > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > =================================================================== > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_64.c > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > 150,158,159,128,136,177,178,176,142,152,173,140 > }; > > +/* Check if URB is managed by KDB code */ > +int kdb_uhci_keyboard_urb(struct urb *urb) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > + > +/* Check if UHCI QH is managed by KDB code */ > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > + > +/* Clear keyboar entry */ > +int kdb_uhci_keyboard_clear(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].urb = NULL; > + kdb_usb_kbds[i].buffer = NULL; > + kdb_usb_kbds[i].poll_func = NULL; > + kdb_usb_kbds[i].urb_complete = NULL; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > + > +/* Set UHCI QH using URB pointer */ > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].qh = qh; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > + > +/* Get UHCI QH using URB pointer */ > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].qh; > + } > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > + > +/* Set UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > + > +/* Get UHCI hid_event using URB pointer */ > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > +{ > + int i; > + > + i = kdb_uhci_keyboard_urb(urb); > + if (i != -1){ > + /* found a free array index */ > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > + > +/* Set UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > + return i; > + } > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > + > +/* Get UHCI hid_event using UHCI QH pointer */ > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > +{ > + int i; > + > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > + return kdb_usb_kbds[i].kdb_hid_event; > + } > + > + return -1; > +} > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > + > /* > * kdb_usb_keyboard_attach() > * Attach a USB keyboard to kdb. > */ > int > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > + void *poll_func, void *compl_func) > { > int i; > int rc = -1; > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > kdb_usb_kbds[i].urb = urb; > kdb_usb_kbds[i].buffer = buffer; > kdb_usb_kbds[i].poll_func = poll_func; > + kdb_usb_kbds[i].urb_complete = compl_func; > > rc = 0; /* success */ > > @@ -142,6 +277,9 @@ get_usb_char(void) > int ret; > unsigned char keycode, spec; > extern u_short plain_map[], shift_map[], ctrl_map[]; > + int poll_ret, i2, j, max; > + > + ret = -1; > > if (kdb_no_usb) > return -1; > @@ -158,20 +296,27 @@ get_usb_char(void) > continue; > > /* Transfer char */ > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > - if (ret == -1) /* error or no characters, try the next kbd */ > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > continue; > > + /* If 2 keys was pressed simultaneously, > + * both keycodes will be in buffer. > + * Last pressed key will be last non > + * zero byte. > + */ > + for (j=0; j<4; j++){ > + if (!kdb_usb_kbds[i].buffer[2+j]) > + break; > + } > + /* Last pressed key */ > + max = j + 1; > + > spec = kdb_usb_kbds[i].buffer[0]; > - keycode = kdb_usb_kbds[i].buffer[2]; > + keycode = kdb_usb_kbds[i].buffer[max]; > kdb_usb_kbds[i].buffer[0] = (char)0; > kdb_usb_kbds[i].buffer[2] = (char)0; > > - if(kdb_usb_kbds[i].buffer[3]) { > - kdb_usb_kbds[i].buffer[3] = (char)0; > - continue; > - } > - > /* A normal key is pressed, decode it */ > if(keycode) > keycode = kdb_usb_keycode[keycode]; > @@ -182,10 +327,12 @@ get_usb_char(void) > { > case 0x2: > case 0x20: /* Shift */ > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > case 0x1: > case 0x10: /* Ctrl */ > - return ctrl_map[keycode]; > + ret = ctrl_map[keycode]; > + break; > case 0x4: > case 0x40: /* Alt */ > break; > @@ -194,31 +341,45 @@ get_usb_char(void) > switch(keycode) > { > case 0x1C: /* Enter */ > - return 13; > - > + ret = 13; > + break; > case 0x3A: /* Capslock */ > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > break; > case 0x0E: /* Backspace */ > - return 8; > + ret = 8; > + break; > case 0x0F: /* TAB */ > - return 9; > + ret = 9; > + break; > case 0x77: /* Pause */ > break ; > default: > if(!kdb_usb_kbds[i].caps_lock) { > - return plain_map[keycode]; > + ret = plain_map[keycode]; > + break; > } > else { > - return shift_map[keycode]; > + ret = shift_map[keycode]; > + break; > } > } > } > + /* Key was pressed, return keycode */ > + break; > } > > - /* no chars were returned from any of the USB keyboards */ > + for(i2=0; i2<8; i2++){ > + if (kdb_usb_kbds[i2].buffer) > + for(j=0; j<8; j++){ > + kdb_usb_kbds[i2].buffer[j] = (char)0; > + } > + } > + > + if (kdb_usb_kbds[i].urb_complete) > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > - return -1; > + return ret; > } > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/include/linux/kdbprivate.h > =================================================================== > --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h > +++ linux-2.6.24-rc2/include/linux/kdbprivate.h > @@ -489,7 +489,10 @@ struct kdb_usb_kbd_info { > struct urb *urb; /* pointer to the URB */ > unsigned char *buffer; /* pointer to the kbd char buffer */ > int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ > + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ > int caps_lock; /* state of the caps lock for this keyboard */ > + struct uhci_qh *qh; > + int kdb_hid_event; > }; > #endif /* CONFIG_KDB_USB */ > > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c > @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev > return NULL; > } > EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > + > +void * > +usb_hcd_get_kdb_completion_func(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver) > + return (void *)(hcd->driver->kdb_completion); > + > + return NULL; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); > + > +int > +usb_hcd_check_uhci(struct usb_device *udev) > +{ > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > + > + if (hcd && hcd->driver){ > + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) > + return 1; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); > #endif /* CONFIG_KDB_USB */ > > /*-------------------------------------------------------------------------*/ > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h > =================================================================== > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h > @@ -213,6 +213,7 @@ struct hc_driver { > #ifdef CONFIG_KDB_USB > /* KDB poll function for this HC */ > int (*kdb_poll_char)(struct urb *urb); > + void (*kdb_completion)(struct urb *urb); > #endif /* CONFIG_KDB_USB */ > }; > > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. > --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 30 08:42:59 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 08:43:08 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUGgxEu011605 for ; Fri, 30 Nov 2007 08:42:59 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAUGh8K910015899; Fri, 30 Nov 2007 08:43:08 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAUGh7ig10071434; Fri, 30 Nov 2007 08:43:07 -0800 (PST) From: Aaron Young Message-Id: <200711301643.lAUGh7ig10071434@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: ayoung@engr.sgi.com (Aaron Young) Date: Fri, 30 Nov 2007 08:43:07 -0800 (PST) Cc: kbaidarov@ru.mvista.com (Konstantin Baydarov), ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> from "Aaron Young" at Nov 30, 2007 07:52:59 AM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1300 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb Also, should kdb_uhci_keyboard_chech_uhci_qh() be kdb_uhci_keyboard_check_uhci_qh()? > > > > Looking better! More comments: > > 1. I don't understand the need for the call to > kdb_uhci_keyboard_clear(). It's only called if > kdb_usb_keyboard_attach() fails and in that case we > didn't add the urb to kdb_usb_kbds[]. So, I don't > see the need to clear it out of kdb_usb_kbds[]... > (I'm probably missing something here). > > 2. I probably would have made kdb_uhci_submit_urb() return > the newly created kdb_urb (extra arg) on success and not call > kdb_usb_keyboard_attach() directly from within. Then you can just make a > single call to kdb_usb_keyboard_attach() for all three > cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not > a *BIG* deal... > > 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise > it will result in compile errors on ia64. i.e. kdb_usb_keyboard_attach() > will have a number of args mismatch and all the routines you > added to kdba_io_32.c and kdba_io_64.c will not be there. > > 4. You have the comment "/* found a free array index */" in several > of the new kdba_io*.c routines when it really means you found > a "match". > > 5. I just submitted another patch on Wed (Nov. 28th). That will > conflict with this one again. Sorry - should be my last patch. > > > Does hotplug/hotunplug of the keyboards work? > Does it correctly remove the KDB URBs on hotunplug? > > Thanks, > > -Aaron > > > > > > > > > > > > > On Mon, 26 Nov 2007 13:39:41 -0800 (PST) > > Aaron Young wrote: > > > > > > > > > > > Konstantin, some comments: > > > > > > 1. You added some USB specific code to kdba_io_32.c, namely > > > kdb_usb_fill_int_urb(), kdb_uhci_submit_urb(). > > > > > > Would it be better to put this USB code into the kernel uhci > > > files (uhci-q.c, uhci-hcd.c or whatever) so kdb can remain unaware > > > of USB specifics? > > > Also, I think if you did it this way, then it would remove the need > > > for the new interface routine kdb_usb_uhci_keyboard_attach(). You > > > should be able to just call kdb_usb_keyboard_attach() after you > > > create and submit the new URB from hid_probe(). Just add > > > a new parameter to kdb_usb_keyboard_attach() for the > > > complete_func and pass NULL for it for OHCI and EHCI. > > > > > > The USB infastructure is constantly being rewritten and > > > structures/parameters changing around, so it would be best to keep > > > those details over in the kernel and not in kdb IMO. > > > > > - Got rid from kdb_usb_uhci_keyboard_attach() > > - Added "poll_func" argument to kdb_usb_keyboard_attach() > > - Moved kdb_usb_fill_int_urb() and kdb_uhci_submit_urb() to hid-core.c. That fixes compilation errors (problem reported by jidong xiao) when USB subsystem is compiled as kernel module. > > > > > 2. What is the limiting factor preventing multiple keyboards? Is it > > > the use of the globals kdb_uhci_hid_qh and kdb_hid_event? Can this > > > be fixed somehow? Can they be put into the per device > > > kdb_usb_kbd_info struct maybe? > > > > > - Moved kdb_uhci_hid_qh and hid_event to kdb_usb_kbd_info. Now multiple UHCI keyboards are supported. > > > > > 4. I think you'll need to add your new interfaces to kdba_io_64.c > > > and arch/ia64/kdb/kdba_io.c. Otherwise, the USB modules will > > > encounter link/build errors when they can't find > > > kdb_usb_uhci_keyboard_attach() (and the other globals and such) on > > > those builds/systems. It would be nice to have UHCI support on those > > > archs too. > > > > > - Added x86_64 part. > > > > > 5. I already submitted another patch for EHCI support which will > > > conflict with this one (kdba_io_32.c). Can you add your patch on > > > top of that one? > > - Done. > > > > > > > > > > > -Aaron > > > > > > > Patch against kernel 2.6.24-rc2. Was tested on i386 kernel with 2 UHCI keyboards. > > > > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c > > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c > > @@ -25,6 +25,18 @@ > > * games with the FSBR code to make sure we get the correct order in all > > * the cases. I don't think it's worth the effort > > */ > > +#ifdef CONFIG_KDB_USB > > +/* KDB HID QH, managed by KDB code */ > > +extern int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh); > > +extern int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); > > +extern struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); > > +extern int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); > > +extern int kdb_uhci_keyboard_get_hid_event(struct urb *urb); > > +extern int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); > > +extern int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh); > > +#endif > > + > > + > > static void uhci_set_next_interrupt(struct uhci_hcd *uhci) > > { > > if (uhci->is_stopped) > > @@ -292,6 +304,58 @@ static struct uhci_qh *uhci_alloc_qh(str > > return qh; > > } > > > > +#ifdef CONFIG_KDB_USB > > +/* > > + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv > > + */ > > +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, > > + struct usb_device *udev, struct usb_host_endpoint *hep) > > +{ > > + dma_addr_t dma_handle; > > + struct uhci_qh *qh; > > + > > + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); > > + if (!qh) > > + return NULL; > > + > > + memset(qh, 0, sizeof(*qh)); > > + qh->dma_handle = dma_handle; > > + > > + qh->element = UHCI_PTR_TERM; > > + qh->link = UHCI_PTR_TERM; > > + > > + INIT_LIST_HEAD(&qh->queue); > > + INIT_LIST_HEAD(&qh->node); > > + > > + if (udev) { /* Normal QH */ > > + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; > > + if (qh->type != USB_ENDPOINT_XFER_ISOC) { > > + qh->dummy_td = uhci_alloc_td(uhci); > > + if (!qh->dummy_td) { > > + dma_pool_free(uhci->qh_pool, qh, dma_handle); > > + return NULL; > > + } > > + } > > + qh->state = QH_STATE_IDLE; > > + qh->hep = hep; > > + qh->udev = udev; > > + > > + if (qh->type == USB_ENDPOINT_XFER_INT || > > + qh->type == USB_ENDPOINT_XFER_ISOC) > > + qh->load = usb_calc_bus_time(udev->speed, > > + usb_endpoint_dir_in(&hep->desc), > > + qh->type == USB_ENDPOINT_XFER_ISOC, > > + le16_to_cpu(hep->desc.wMaxPacketSize)) > > + / 1000 + 1; > > + > > + } else { /* Skeleton QH */ > > + qh->state = QH_STATE_ACTIVE; > > + qh->type = -1; > > + } > > + return qh; > > +} > > +#endif > > + > > static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) > > { > > WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); > > @@ -1399,6 +1463,20 @@ static int uhci_urb_enqueue(struct usb_h > > if (!urbp) > > goto done; > > > > +#ifdef CONFIG_KDB_USB > > + /* Always allocate new QH for KDB URB. > > + * KDB HQ will be managed by KDB poll code not by > > + * UHCI HCD Driver. > > + */ > > + if (kdb_uhci_keyboard_urb(urb) != -1){ > > + /* KDB urb will be enqued only once */ > > + kdb_uhci_keyboard_set_qh(urb, NULL); > > + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); > > + if (!qh) > > + goto err_no_qh; > > + kdb_uhci_keyboard_set_qh(urb, qh); > > + } else > > +#endif > > if (urb->ep->hcpriv) > > qh = urb->ep->hcpriv; > > else { > > @@ -1648,6 +1726,13 @@ static int uhci_advance_check(struct uhc > > int ret = 1; > > unsigned status; > > > > +#ifdef CONFIG_KDB_USB > > + /* Don't manage KDB QH */ > > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1){ > > + ret = 0; > > + goto done; > > + } > > +#endif > > if (qh->type == USB_ENDPOINT_XFER_ISOC) > > goto done; > > > > @@ -1740,6 +1825,11 @@ rescan: > > uhci->next_qh = list_entry(qh->node.next, > > struct uhci_qh, node); > > > > +#ifdef CONFIG_KDB_USB > > + /* Don't manage KDB QH */ > > + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1) > > + continue; > > +#endif > > if (uhci_advance_check(uhci, qh)) { > > uhci_scan_qh(uhci, qh); > > if (qh->state == QH_STATE_ACTIVE) { > > @@ -1766,3 +1856,76 @@ rescan: > > else > > uhci_set_next_interrupt(uhci); > > } > > + > > +#ifdef CONFIG_KDB_USB > > +/* > > + * Activate KDB UHCI QH, called by KDB poll code. > > + */ > > +static void kdb_activate_uhci_qh(struct uhci_qh *qh) > > +{ > > + struct urb_priv *urbp; > > + struct uhci_td *td; > > + __le32 status, token; > > + > > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > > + > > + list_for_each_entry(td, &urbp->td_list, list){ > > + status = td->status; > > + token = td->token; > > + barrier(); > > + /* Clear Status and ActLen */ > > + status &= cpu_to_le32(0xff000000); > > + /* Make TD Active */ > > + status |= cpu_to_le32(TD_CTRL_ACTIVE); > > + /* Clear TD Interrupt */ > > + status &= cpu_to_le32(~TD_CTRL_IOC); > > + /* Toggle Data Sycronization Bit */ > > + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) > > + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); > > + else > > + token |= cpu_to_le32(TD_TOKEN_TOGGLE); > > + > > + td->token = token; > > + td->status = status; > > + barrier(); > > + } > > + /* Activate KDB UHCI Keyboard HID QH */ > > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > > + qh->element = LINK_TO_TD(td); > > + barrier(); > > +} > > + > > +/* > > + * Called when KDB finishes process key press/release event. > > + */ > > +static void > > +kdb_uhci_urb_complete (struct urb *urb) > > +{ > > + if (!kdb_uhci_keyboard_get_hid_event(urb)) > > + return; > > + > > + /* Activate KDB TD */ > > + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > > + kdb_uhci_keyboard_set_hid_event(urb, 0); > > +} > > + > > +/* > > + * Check if state of KDB URB changed (key was pressed/released). > > + */ > > +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) > > +{ > > + struct urb_priv *urbp = NULL; > > + struct uhci_td *td; > > + unsigned status; > > + > > + urbp = list_entry(qh->queue.next, struct urb_priv, node); > > + td = list_entry(urbp->td_list.next, struct uhci_td, list); > > + status = td_status(td); > > + if (!(status & TD_CTRL_ACTIVE)){ > > + /* We're okay, the queue has advanced */ > > + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); > > + return 0; > > + } > > + return -1; > > +} > > +#endif > > Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c > > +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c > > @@ -969,6 +969,86 @@ static void hid_disconnect(struct usb_in > > hid_free_device(hid); > > } > > > > +#ifdef CONFIG_KDB_USB > > +/* Only 1 UHCI Keyboard supported */ > > +static inline void kdb_usb_fill_int_urb (struct urb *urb, > > + struct usb_device *dev, > > + unsigned int pipe, > > + void *transfer_buffer, > > + int buffer_length, > > + usb_complete_t complete_fn, > > + void *context, > > + int interval) > > +{ > > + urb->dev = dev; > > + urb->pipe = pipe; > > + urb->transfer_buffer = transfer_buffer; > > + urb->transfer_buffer_length = buffer_length; > > + urb->complete = complete_fn; > > + urb->context = context; > > + urb->interval = interval; > > + urb->start_frame = -1; > > +} > > + > > +static int kdb_uhci_submit_urb(struct usb_interface *intf, unsigned int usbhid_bufsize, struct urb *hid_inurb) > > +{ > > + struct urb *kdb_urb = NULL; > > + unsigned char *kdb_buffer; > > + dma_addr_t uhci_inbuf_dma; > > + int ret = -1; > > + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > > + > > + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, > > + usbhid_bufsize, GFP_ATOMIC, > > + &uhci_inbuf_dma))) > > + goto out; > > + > > + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) > > + goto out; > > + > > + kdb_usb_fill_int_urb(kdb_urb, > > + hid_inurb->dev, > > + hid_inurb->pipe, > > + kdb_buffer, > > + hid_inurb->transfer_buffer_length, > > + hid_inurb->complete, > > + hid_inurb->context, > > + hid_inurb->interval > > + ); > > + > > + (kdb_urb)->transfer_dma = uhci_inbuf_dma; > > + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > > + > > + ret = kdb_usb_keyboard_attach(kdb_urb, kdb_buffer, > > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > > + > > + if (ret){ > > + kdb_uhci_keyboard_clear(kdb_urb); > > + goto out; > > + } > > + > > + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)) > > + goto out; > > + > > + ret = 0; > > + return ret; > > +out: > > + /* Some Error Cleanup */ > > + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); > > + if (kdb_buffer) > > + usb_buffer_free(hid_inurb->dev, > > + usbhid_bufsize, kdb_buffer, > > + uhci_inbuf_dma); > > + > > + if (kdb_urb) > > + usb_free_urb(kdb_urb); > > + > > + return ret; > > +} > > +#endif > > + > > static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) > > { > > struct hid_device *hid; > > @@ -1045,8 +1125,15 @@ static int hid_probe(struct usb_interfac > > int ret; > > struct usbhid_device *usbhid = hid->driver_data; > > extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); > > - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > > - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); > > + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); > > + extern int usb_hcd_check_uhci(struct usb_device *udev); > > + > > + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) > > + ret = kdb_uhci_submit_urb(intf, usbhid->bufsize, usbhid->urbin); > > + else > > + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, > > + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), > > + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf))); > > > > if (ret == -1) > > printk(": FAILED to register keyboard (%s) " > > Index: linux-2.6.24-rc2/include/linux/kdb.h > > =================================================================== > > --- linux-2.6.24-rc2.orig/include/linux/kdb.h > > +++ linux-2.6.24-rc2/include/linux/kdb.h > > @@ -143,9 +143,17 @@ extern void smp_kdb_stop(void); > > > > #include > > > > -extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); > > +extern int kdb_uhci_keyboard_urb(struct urb *urb); > > +extern int kdb_uhci_keyboard_clear(struct urb *urb); > > +extern int kdb_usb_keyboard_alloc(void); > > + > > +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func, void *compl_func); > > extern int kdb_usb_keyboard_detach(struct urb *urb); > > > > +extern int > > +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, > > + void *poll_func, void *compl_func); > > + > > #endif /* CONFIG_KDB_USB */ > > > > static inline > > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c > > +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c > > @@ -50,6 +50,10 @@ > > #include "uhci-hcd.h" > > #include "pci-quirks.h" > > > > +#ifdef CONFIG_KDB_USB > > +#include > > +#endif > > + > > /* > > * Version Information > > */ > > @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h > > return IRQ_HANDLED; > > } > > > > +#ifdef CONFIG_KDB_USB > > +static int > > +uhci_kdb_poll_char(struct urb *urb) > > +{ > > + if (!urb) /* can happen if no keyboard attached */ > > + return -1; > > + > > + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); > > +} > > +#endif > > + > > /* > > * Store the current frame number in uhci->frame_number if the controller > > * is runnning. Expand from 11 bits (of which we use only 10) to a > > @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive > > > > .hub_status_data = uhci_hub_status_data, > > .hub_control = uhci_hub_control, > > +#ifdef CONFIG_KDB_USB > > + .kdb_poll_char = uhci_kdb_poll_char, > > + .kdb_completion = kdb_uhci_urb_complete, > > +#endif > > }; > > > > static const struct pci_device_id uhci_pci_ids[] = { { > > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c > > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c > > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > > 150,158,159,128,136,177,178,176,142,152,173,140 > > }; > > > > +/* Check if URB is managed by KDB code */ > > +int kdb_uhci_keyboard_urb(struct urb *urb) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > > + return i; > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > > + > > +/* Check if UHCI QH is managed by KDB code */ > > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > > + return i; > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > > + > > +/* Clear keyboar entry */ > > +int kdb_uhci_keyboard_clear(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].urb = NULL; > > + kdb_usb_kbds[i].buffer = NULL; > > + kdb_usb_kbds[i].poll_func = NULL; > > + kdb_usb_kbds[i].urb_complete = NULL; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > > + > > +/* Set UHCI QH using URB pointer */ > > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].qh = qh; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > > + > > +/* Get UHCI QH using URB pointer */ > > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + return kdb_usb_kbds[i].qh; > > + } > > + > > + return NULL; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > > + > > +/* Set UHCI hid_event using URB pointer */ > > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > > + > > +/* Get UHCI hid_event using URB pointer */ > > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + return kdb_usb_kbds[i].kdb_hid_event; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > > + > > +/* Set UHCI hid_event using UHCI QH pointer */ > > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > > + return i; > > + } > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > > + > > +/* Get UHCI hid_event using UHCI QH pointer */ > > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > > + return kdb_usb_kbds[i].kdb_hid_event; > > + } > > + > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > > + > > /* > > * kdb_usb_keyboard_attach() > > * Attach a USB keyboard to kdb. > > */ > > int > > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > > + void *poll_func, void *compl_func) > > { > > int i; > > int rc = -1; > > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > > kdb_usb_kbds[i].urb = urb; > > kdb_usb_kbds[i].buffer = buffer; > > kdb_usb_kbds[i].poll_func = poll_func; > > + kdb_usb_kbds[i].urb_complete = compl_func; > > > > rc = 0; /* success */ > > > > @@ -142,6 +277,9 @@ get_usb_char(void) > > int ret; > > unsigned char keycode, spec; > > extern u_short plain_map[], shift_map[], ctrl_map[]; > > + int poll_ret, i2, j, max; > > + > > + ret = -1; > > > > if (kdb_no_usb) > > return -1; > > @@ -158,20 +296,27 @@ get_usb_char(void) > > continue; > > > > /* Transfer char */ > > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > > - if (ret == -1) /* error or no characters, try the next kbd */ > > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > > continue; > > > > + /* If 2 keys was pressed simultaneously, > > + * both keycodes will be in buffer. > > + * Last pressed key will be last non > > + * zero byte. > > + */ > > + for (j=0; j<4; j++){ > > + if (!kdb_usb_kbds[i].buffer[2+j]) > > + break; > > + } > > + /* Last pressed key */ > > + max = j + 1; > > + > > spec = kdb_usb_kbds[i].buffer[0]; > > - keycode = kdb_usb_kbds[i].buffer[2]; > > + keycode = kdb_usb_kbds[i].buffer[max]; > > kdb_usb_kbds[i].buffer[0] = (char)0; > > kdb_usb_kbds[i].buffer[2] = (char)0; > > > > - if(kdb_usb_kbds[i].buffer[3]) { > > - kdb_usb_kbds[i].buffer[3] = (char)0; > > - continue; > > - } > > - > > /* A normal key is pressed, decode it */ > > if(keycode) > > keycode = kdb_usb_keycode[keycode]; > > @@ -182,10 +327,12 @@ get_usb_char(void) > > { > > case 0x2: > > case 0x20: /* Shift */ > > - return shift_map[keycode]; > > + ret = shift_map[keycode]; > > + break; > > case 0x1: > > case 0x10: /* Ctrl */ > > - return ctrl_map[keycode]; > > + ret = ctrl_map[keycode]; > > + break; > > case 0x4: > > case 0x40: /* Alt */ > > break; > > @@ -194,31 +341,45 @@ get_usb_char(void) > > switch(keycode) > > { > > case 0x1C: /* Enter */ > > - return 13; > > - > > + ret = 13; > > + break; > > case 0x3A: /* Capslock */ > > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > > break; > > case 0x0E: /* Backspace */ > > - return 8; > > + ret = 8; > > + break; > > case 0x0F: /* TAB */ > > - return 9; > > + ret = 9; > > + break; > > case 0x77: /* Pause */ > > break ; > > default: > > if(!kdb_usb_kbds[i].caps_lock) { > > - return plain_map[keycode]; > > + ret = plain_map[keycode]; > > + break; > > } > > else { > > - return shift_map[keycode]; > > + ret = shift_map[keycode]; > > + break; > > } > > } > > } > > + /* Key was pressed, return keycode */ > > + break; > > } > > > > - /* no chars were returned from any of the USB keyboards */ > > + for(i2=0; i2<8; i2++){ > > + if (kdb_usb_kbds[i2].buffer) > > + for(j=0; j<8; j++){ > > + kdb_usb_kbds[i2].buffer[j] = (char)0; > > + } > > + } > > + > > + if (kdb_usb_kbds[i].urb_complete) > > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > > > - return -1; > > + return ret; > > } > > #endif /* CONFIG_KDB_USB */ > > > > Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_64.c > > +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c > > @@ -55,12 +55,146 @@ static unsigned char kdb_usb_keycode[256 > > 150,158,159,128,136,177,178,176,142,152,173,140 > > }; > > > > +/* Check if URB is managed by KDB code */ > > +int kdb_uhci_keyboard_urb(struct urb *urb) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) > > + return i; > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); > > + > > +/* Check if UHCI QH is managed by KDB code */ > > +int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > > + return i; > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); > > + > > +/* Clear keyboar entry */ > > +int kdb_uhci_keyboard_clear(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].urb = NULL; > > + kdb_usb_kbds[i].buffer = NULL; > > + kdb_usb_kbds[i].poll_func = NULL; > > + kdb_usb_kbds[i].urb_complete = NULL; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); > > + > > +/* Set UHCI QH using URB pointer */ > > +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].qh = qh; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); > > + > > +/* Get UHCI QH using URB pointer */ > > +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + return kdb_usb_kbds[i].qh; > > + } > > + > > + return NULL; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); > > + > > +/* Set UHCI hid_event using URB pointer */ > > +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); > > + > > +/* Get UHCI hid_event using URB pointer */ > > +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) > > +{ > > + int i; > > + > > + i = kdb_uhci_keyboard_urb(urb); > > + if (i != -1){ > > + /* found a free array index */ > > + return kdb_usb_kbds[i].kdb_hid_event; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); > > + > > +/* Set UHCI hid_event using UHCI QH pointer */ > > +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ > > + kdb_usb_kbds[i].kdb_hid_event = hid_event; > > + return i; > > + } > > + } > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); > > + > > +/* Get UHCI hid_event using UHCI QH pointer */ > > +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) > > +{ > > + int i; > > + > > + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { > > + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) > > + return kdb_usb_kbds[i].kdb_hid_event; > > + } > > + > > + return -1; > > +} > > +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); > > + > > /* > > * kdb_usb_keyboard_attach() > > * Attach a USB keyboard to kdb. > > */ > > int > > -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) > > +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, > > + void *poll_func, void *compl_func) > > { > > int i; > > int rc = -1; > > @@ -82,6 +216,7 @@ kdb_usb_keyboard_attach(struct urb *urb, > > kdb_usb_kbds[i].urb = urb; > > kdb_usb_kbds[i].buffer = buffer; > > kdb_usb_kbds[i].poll_func = poll_func; > > + kdb_usb_kbds[i].urb_complete = compl_func; > > > > rc = 0; /* success */ > > > > @@ -142,6 +277,9 @@ get_usb_char(void) > > int ret; > > unsigned char keycode, spec; > > extern u_short plain_map[], shift_map[], ctrl_map[]; > > + int poll_ret, i2, j, max; > > + > > + ret = -1; > > > > if (kdb_no_usb) > > return -1; > > @@ -158,20 +296,27 @@ get_usb_char(void) > > continue; > > > > /* Transfer char */ > > - ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > > - if (ret == -1) /* error or no characters, try the next kbd */ > > + poll_ret = (*kdb_usb_kbds[i].poll_func)(kdb_usb_kbds[i].urb); > > + if (poll_ret == -1) /* error or no characters, try the next kbd */ > > continue; > > > > + /* If 2 keys was pressed simultaneously, > > + * both keycodes will be in buffer. > > + * Last pressed key will be last non > > + * zero byte. > > + */ > > + for (j=0; j<4; j++){ > > + if (!kdb_usb_kbds[i].buffer[2+j]) > > + break; > > + } > > + /* Last pressed key */ > > + max = j + 1; > > + > > spec = kdb_usb_kbds[i].buffer[0]; > > - keycode = kdb_usb_kbds[i].buffer[2]; > > + keycode = kdb_usb_kbds[i].buffer[max]; > > kdb_usb_kbds[i].buffer[0] = (char)0; > > kdb_usb_kbds[i].buffer[2] = (char)0; > > > > - if(kdb_usb_kbds[i].buffer[3]) { > > - kdb_usb_kbds[i].buffer[3] = (char)0; > > - continue; > > - } > > - > > /* A normal key is pressed, decode it */ > > if(keycode) > > keycode = kdb_usb_keycode[keycode]; > > @@ -182,10 +327,12 @@ get_usb_char(void) > > { > > case 0x2: > > case 0x20: /* Shift */ > > - return shift_map[keycode]; > > + ret = shift_map[keycode]; > > + break; > > case 0x1: > > case 0x10: /* Ctrl */ > > - return ctrl_map[keycode]; > > + ret = ctrl_map[keycode]; > > + break; > > case 0x4: > > case 0x40: /* Alt */ > > break; > > @@ -194,31 +341,45 @@ get_usb_char(void) > > switch(keycode) > > { > > case 0x1C: /* Enter */ > > - return 13; > > - > > + ret = 13; > > + break; > > case 0x3A: /* Capslock */ > > kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); > > break; > > case 0x0E: /* Backspace */ > > - return 8; > > + ret = 8; > > + break; > > case 0x0F: /* TAB */ > > - return 9; > > + ret = 9; > > + break; > > case 0x77: /* Pause */ > > break ; > > default: > > if(!kdb_usb_kbds[i].caps_lock) { > > - return plain_map[keycode]; > > + ret = plain_map[keycode]; > > + break; > > } > > else { > > - return shift_map[keycode]; > > + ret = shift_map[keycode]; > > + break; > > } > > } > > } > > + /* Key was pressed, return keycode */ > > + break; > > } > > > > - /* no chars were returned from any of the USB keyboards */ > > + for(i2=0; i2<8; i2++){ > > + if (kdb_usb_kbds[i2].buffer) > > + for(j=0; j<8; j++){ > > + kdb_usb_kbds[i2].buffer[j] = (char)0; > > + } > > + } > > + > > + if (kdb_usb_kbds[i].urb_complete) > > + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); > > > > - return -1; > > + return ret; > > } > > #endif /* CONFIG_KDB_USB */ > > > > Index: linux-2.6.24-rc2/include/linux/kdbprivate.h > > =================================================================== > > --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h > > +++ linux-2.6.24-rc2/include/linux/kdbprivate.h > > @@ -489,7 +489,10 @@ struct kdb_usb_kbd_info { > > struct urb *urb; /* pointer to the URB */ > > unsigned char *buffer; /* pointer to the kbd char buffer */ > > int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ > > + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ > > int caps_lock; /* state of the caps lock for this keyboard */ > > + struct uhci_qh *qh; > > + int kdb_hid_event; > > }; > > #endif /* CONFIG_KDB_USB */ > > > > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c > > =================================================================== > > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c > > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c > > @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev > > return NULL; > > } > > EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); > > + > > +void * > > +usb_hcd_get_kdb_completion_func(struct usb_device *udev) > > +{ > > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > > + > > + if (hcd && hcd->driver) > > + return (void *)(hcd->driver->kdb_completion); > > + > > + return NULL; > > +} > > +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); > > + > > +int > > +usb_hcd_check_uhci(struct usb_device *udev) > > +{ > > + struct usb_hcd *hcd = bus_to_hcd(udev->bus); > > + > > + if (hcd && hcd->driver){ > > + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) > > + return 1; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); > > #endif /* CONFIG_KDB_USB */ > > > > /*-------------------------------------------------------------------------*/ > > Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h > > =================================================================== > > --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h > > +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h > > @@ -213,6 +213,7 @@ struct hc_driver { > > #ifdef CONFIG_KDB_USB > > /* KDB poll function for this HC */ > > int (*kdb_poll_char)(struct urb *urb); > > + void (*kdb_completion)(struct urb *urb); > > #endif /* CONFIG_KDB_USB */ > > }; > > > > --------------------------- > > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. > > > > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. > --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 30 09:00:44 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 09:00:51 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUH0g8c019294 for ; Fri, 30 Nov 2007 09:00:44 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAUH0pK910090425; Fri, 30 Nov 2007 09:00:51 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAUH0o8l10107350; Fri, 30 Nov 2007 09:00:50 -0800 (PST) From: Aaron Young Message-Id: <200711301700.lAUH0o8l10107350@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: ayoung@engr.sgi.com (Aaron Young) Date: Fri, 30 Nov 2007 09:00:50 -0800 (PST) Cc: kbaidarov@ru.mvista.com (Konstantin Baydarov), ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> from "Aaron Young" at Nov 30, 2007 07:52:59 AM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1301 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb Another thing, I think we need to update these files: arch/ia64/Kconfig.debug arch/x86/Kconfig.debug to change this line: depends on KDB && USB_OHCI_HCD to: depends on KDB && USB_OHCI_HCD && USB_UHCI_HCD && USB_EHCI_HCD Jay? -Aaron --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Fri Nov 30 09:37:10 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 09:37:18 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUHbAph026459 for ; Fri, 30 Nov 2007 09:37:10 -0800 Received: from [134.15.0.4] (mtv-vpn-sw-corp-0-4.corp.sgi.com [134.15.0.4]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lAUHbGke026232; Fri, 30 Nov 2007 09:37:17 -0800 Message-ID: <47504A4A.6080800@sgi.com> Date: Fri, 30 Nov 2007 09:37:14 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: "Randy.Dunlap" CC: Aaron Young , Konstantin Baydarov , kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI References: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> <200711301700.lAUH0o8l10107350@kluge.engr.sgi.com> <20071130091912.e89d42ac.randy.dunlap@verizon.net> In-Reply-To: <20071130091912.e89d42ac.randy.dunlap@verizon.net> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1302 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Randy.Dunlap wrote: > On Fri, 30 Nov 2007 09:00:50 -0800 (PST) Aaron Young wrote: > >> >> Another thing, I think we need to update these files: >> >> arch/ia64/Kconfig.debug >> arch/x86/Kconfig.debug >> >> to change this line: >> depends on KDB && USB_OHCI_HCD >> >> to: >> >> depends on KDB && USB_OHCI_HCD && USB_UHCI_HCD && USB_EHCI_HCD > > I don't have the complete patch in front of me, but why would > all 3 of those HCDs be needed? I would expect it to be more like > > depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD) Yep, should be a || instead. So, a new depend line will be: depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD || USB_EHCI_HCD) > > and even omit the EHCI_HCD part since it is only for high-speed > devices and I've never seen a keyboard that is a high-speed USB > device. If you connect through a USB 2.0 hub, you will need EHCI_HCD. Thanks, - jay > > (or maybe I'm way out of context...) > >> Jay? > > > --- > ~Randy --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 30 09:47:32 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 09:47:37 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUHlUJ2027538 for ; Fri, 30 Nov 2007 09:47:32 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAUHldK910106945; Fri, 30 Nov 2007 09:47:39 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAUHlcOX10035369; Fri, 30 Nov 2007 09:47:38 -0800 (PST) From: Aaron Young Message-Id: <200711301747.lAUHlcOX10035369@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: randy.dunlap@verizon.net (Randy.Dunlap) Date: Fri, 30 Nov 2007 09:47:38 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), kbaidarov@ru.mvista.com (Konstantin Baydarov), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <20071130091912.e89d42ac.randy.dunlap@verizon.net> from "Randy.Dunlap" at Nov 30, 2007 09:19:12 AM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1303 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb > > On Fri, 30 Nov 2007 09:00:50 -0800 (PST) Aaron Young wrote: > > > > > > > Another thing, I think we need to update these files: > > > > arch/ia64/Kconfig.debug > > arch/x86/Kconfig.debug > > > > to change this line: > > depends on KDB && USB_OHCI_HCD > > > > to: > > > > depends on KDB && USB_OHCI_HCD && USB_UHCI_HCD && USB_EHCI_HCD > > I don't have the complete patch in front of me, but why would > all 3 of those HCDs be needed? I would expect it to be more like > > depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD) > > and even omit the EHCI_HCD part since it is only for high-speed > devices and I've never seen a keyboard that is a high-speed USB > device. EHCI HCD will be used if a keyboard is attached via a USB2.0 hub. Perhaps "depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD || USB_EHCI_HCD)" would be better... What led me to this is Konstantin added this field to a KDB private header struct: + struct uhci_qh *qh; Would this compile properly without USB_UHCI_HCD defined (i.e. and the UHCI HCD was not included in the build?) Also, what if the USB HCDs where compiled as separate modules instead of statically linked? Does it (KDB) still compile okay? Seems like we may need a "#include " in this file... (?) Or, perhaps make it a "void *" and cast it to a struct uhci_qh from the USB kernel files before it's actually used? -Aaron --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Fri Nov 30 09:48:50 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 09:48:58 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lAUHmk6e027663 for ; Fri, 30 Nov 2007 09:48:48 -0800 Received: (qmail 29750 invoked from network); 30 Nov 2007 17:48:50 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.195) by mail.dev.rtsoft.ru with SMTP; 30 Nov 2007 17:48:50 -0000 Date: Fri, 30 Nov 2007 20:48:48 +0300 From: Konstantin Baydarov To: kdb@oss.sgi.com Subject: [PATCH] Add global hardware breakpoints support Message-ID: <20071130204848.64e79547@localhost.localdomain> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1304 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb Global HW BP don't work: 1) Install global HW BP root@192.168.2.10:~# root@192.168.2.10:~# D Entering kdb (current=0xc04433a0, pid 0) on processor 0 due to Keyboard Entry [0]kdb> bpha do_sync Forced Instruction(Register) BP #0 at 0xc0181539 (do_sync) is enabled in dr0 globally [0]kdb> go -bash: D: command not found root@192.168.2.10:~# 1) Try CPU 0 root@192.168.2.10:~# root@192.168.2.10:~# taskset -c 0 sync Instruction(Register) breakpoint #0 at 0xc0181539 0xc0181539 do_sync: push %ebx Entering kdb (0xc1b6d030, pid 1319) on processor 0 due to Debug @ 0xc0181539 [0]kdb> go root@192.168.2.10:~# - OK 1) Try CPU 1 root@192.168.2.10:~# root@192.168.2.10:~# taskset -c 1 sync root@192.168.2.10:~# - Doesn't work. Signed-off-by: Konstantin Baydarov Description: This patch adds support for global hardware breakpoints to KDB on x86 targets. Hardware breakpoints are installed by setting per CPU db registers. So to make a hardware breakpoint global it should be installed in db registers on every CPU in system. So global hw bp can't be handle by kdb_bp_install_global and kdb_bp_remove_global because these functions are called only on "monarch" CPU, kdb_bp_install_local and kdb_bp_remove_local should be used instead because these are called for all CPUs. Main changes: - kdb_hardbreaks[KDB_MAXHARDBPT] - The processor architecture hardware breakpoint registers descriptors is defined for every CPU: static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][KDB_MAXHARDBPT]; - "kdb_bp_t" (main breakpint structure) contains hardware breakpoint registers for every CPU: kdbhard_bp_t* bp_hard[NR_CPUS]; - global hardware breakpoint installation and removal is handled by kdb_bp_install_local and kdb_bp_remove_local which are executed on every CPU - kdba_allocbp andkdba_freebp are static, now kdba_alloc_hwbp and kdba_free_hwbp are used for allocating/freeing hardware breakpoint registers. If the hardware breakpoint is global then kdba_alloc_hwbp tries to allocate hardware breakpoint registers on every CPU. If there is no free hardware breakpoint on a CPU the allocation fails. - bph_installed was added to the hardware breakpoint descriptor to track per CPU hardware breakpoint installation. Patch against kernel 2.6.24-rc2 Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_32.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_bp_32.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_32.c @@ -22,10 +22,10 @@ static char *kdba_rwtypes[] = { "Instruc /* * Table describing processor architecture hardware - * breakpoint registers. + * breakpoint registers for every CPU. */ -static kdbhard_bp_t kdb_hardbreaks[KDB_MAXHARDBPT]; +static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][KDB_MAXHARDBPT]; /* * kdba_db_trap @@ -75,6 +75,7 @@ kdba_db_trap(struct pt_regs *regs, int e int i; kdb_dbtrap_t rv = KDB_DB_BPT; kdb_bp_t *bp; + int cpu = smp_processor_id(); if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; @@ -103,8 +104,12 @@ kdba_db_trap(struct pt_regs *regs, int e kdb_printf("bp for this cpu\n"); if (bp->bp_delayed) { bp->bp_delayed = 0; - if (KDB_DEBUG(BP)) + if (KDB_DEBUG(BP)){ + /* Can't be hw breakpoint */ + if (bp->bp_hardtype) + kdb_printf("kdb: Error - hw bp delayed\n"); kdb_printf("kdba_installbp\n"); + } kdba_installbp(regs, bp); if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; @@ -211,8 +216,8 @@ handle: for(i=0, bp=kdb_breakpoints; ibp_free) && (bp->bp_global || bp->bp_cpu == smp_processor_id()) - && (bp->bp_hard) - && (bp->bp_hard->bph_reg == reg)) { + && (bp->bp_hard[cpu]) + && (bp->bp_hard[cpu]->bph_reg == reg)) { /* * Hit this breakpoint. */ @@ -438,12 +443,18 @@ kdba_printbpreg(kdbhard_bp_t *bph) void kdba_printbp(kdb_bp_t *bp) { + int cpu; + kdb_printf("\n is enabled"); if (bp->bp_hardtype) { - kdba_printbpreg(bp->bp_hard); - if (bp->bp_hard->bph_mode != 0) { + if (bp->bp_global) + cpu = smp_processor_id(); + else + cpu = bp->bp_cpu; + kdba_printbpreg(bp->bp_hard[cpu]); + if (bp->bp_hard[cpu]->bph_mode != 0) { kdb_printf(" for %d bytes", - bp->bp_hard->bph_length+1); + bp->bp_hard[cpu]->bph_length+1); } } } @@ -556,7 +567,7 @@ kdba_parsebp(int argc, const char **argv /* * kdba_allocbp * - * Associate a hardware register with a breakpoint. + * Allocate hw register for bp on specific CPU * * Parameters: * None. @@ -570,13 +581,14 @@ kdba_parsebp(int argc, const char **argv * Remarks: */ -kdbhard_bp_t * -kdba_allocbp(kdbhard_bp_t *bph, int *diagp) +static kdbhard_bp_t * +kdba_allocbp(kdbhard_bp_t *bph, int *diagp, unsigned int cpu) { int i; kdbhard_bp_t *newbph; - for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) { + for(i=0; i < KDB_MAXHARDBPT; i++) { + newbph=&(kdb_hardbreaks[cpu][i]); if (newbph->bph_free) { break; } @@ -608,9 +620,49 @@ kdba_allocbp(kdbhard_bp_t *bph, int *dia } /* + * kdba_alloc_hwbp + * + * Associate a hardware registers with a breakpoint. + * If hw bp is global hw registers descriptor will be allocated + * on every CPU. + * + * Parameters: + * bp - hardware bp + * diagp - pointer to variable that will store error when + * function complete + * Outputs: + * None. + * Returns: + * None + * Locking: + * None. + * Remarks: + * Should be called with correct bp->bp_template + */ + +void +kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp) +{ + int i; + + if (bp->bp_global){ + for (i = 0; i < NR_CPUS; ++i) { + if (!cpu_online(i)) + continue; + bp->bp_hard[i] = kdba_allocbp(&bp->bp_template, diagp, i); + if (*diagp) + break; + } + } else { + bp->bp_hard[bp->bp_cpu] = kdba_allocbp(&bp->bp_template, diagp, bp->bp_cpu); + } + bp->bp_hardtype = 1; +} + +/* * kdba_freebp * - * Deallocate a hardware breakpoint + * Deallocate hw registers descriptor for bp on specific CPU * * Parameters: * None. @@ -623,13 +675,57 @@ kdba_allocbp(kdbhard_bp_t *bph, int *dia * Remarks: */ -void +static void kdba_freebp(kdbhard_bp_t *bph) { bph->bph_free = 1; } /* + * kdba_free_hwbp + * + * Frees allocated hw registers descriptors for bp. + * If hw bp is global, hw registers descriptors will be freed + * on every CPU. + * + * Parameters: + * bp - hardware bp + * Outputs: + * None. + * Returns: + * None + * Locking: + * None. + * Remarks: + * Should be called with correct bp->bp_template + */ + +void +kdba_free_hwbp(kdb_bp_t *bp) +{ + int i; + + /* When kernel enters KDB, first, all local bps + * are removed, so here we don't need to clear + * debug registers. + */ + + if (bp->bp_global){ + for (i = 0; i < NR_CPUS; ++i) { + if (!cpu_online(i)) + continue; + if (bp->bp_hard[i]) + kdba_freebp(bp->bp_hard[i]); + bp->bp_hard[i] = 0; + } + } else { + kdba_freebp(bp->bp_hard[bp->bp_cpu]); + bp->bp_hard[bp->bp_cpu] = NULL; + } + bp->bp_hardtype = 0; +} + +/* * kdba_initbp * * Initialize the breakpoint table for the hardware breakpoint @@ -653,7 +749,7 @@ kdba_freebp(kdbhard_bp_t *bph) void kdba_initbp(void) { - int i; + int i,j; kdbhard_bp_t *bph; /* @@ -662,9 +758,15 @@ kdba_initbp(void) memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks)); - for(i=0,bph=kdb_hardbreaks; ibph_reg = i; - bph->bph_free = 1; + for (i = 0; i < NR_CPUS; ++i) { + /* Called early so we don't know actual + * ammount of CPUs + */ + for(j=0; j < KDB_MAXHARDBPT; j++) { + bph=&(kdb_hardbreaks[i][j]); + bph->bph_reg = j; + bph->bph_free = 1; + } } } @@ -698,6 +800,8 @@ kdba_initbp(void) int kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp) { + int cpu = smp_processor_id(); + /* * Install the breakpoint, if it is not already installed. */ @@ -707,15 +811,27 @@ kdba_installbp(struct pt_regs *regs, kdb } if (!KDB_STATE(SSBPT)) bp->bp_delay = 0; - if (!bp->bp_installed) { - if (bp->bp_hardtype) { + + if (bp->bp_hardtype) { + if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){ + kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n"); + } + + if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){ + kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n"); + return 1; + } + + if (!bp->bp_hard[cpu]->bph_installed){ kdba_installdbreg(bp); - bp->bp_installed = 1; + bp->bp_hard[cpu]->bph_installed = 1; if (KDB_DEBUG(BP)) { kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", - bp->bp_hard->bph_reg, bp->bp_addr); + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); } - } else if (bp->bp_delay) { + } + } else if (!bp->bp_installed) { + if (bp->bp_delay) { if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp delayed bp\n"); kdba_handle_bp(regs, bp); @@ -753,6 +869,8 @@ kdba_installbp(struct pt_regs *regs, kdb int kdba_removebp(kdb_bp_t *bp) { + int cpu = smp_processor_id(); + /* * For hardware breakpoints, remove it from the active register, * for software breakpoints, restore the instruction stream. @@ -760,20 +878,36 @@ kdba_removebp(kdb_bp_t *bp) if (KDB_DEBUG(BP)) { kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed); } - if (bp->bp_installed) { - if (bp->bp_hardtype) { + + if (bp->bp_hardtype) { + if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){ + kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n"); + } + + if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){ + kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n"); + return 1; + } + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n", + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); + } + + if (bp->bp_hard[cpu]->bph_installed){ if (KDB_DEBUG(BP)) { - kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n", - bp->bp_hard->bph_reg, bp->bp_addr); + kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); } kdba_removedbreg(bp); - } else { - if (KDB_DEBUG(BP)) - kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n", - bp->bp_inst, bp->bp_addr); - if (kdb_putword(bp->bp_addr, bp->bp_inst, 1)) - return(1); + bp->bp_hard[cpu]->bph_installed = 0; } + } else if (bp->bp_installed) { + if (KDB_DEBUG(BP)) + kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n", + bp->bp_inst, bp->bp_addr); + if (kdb_putword(bp->bp_addr, bp->bp_inst, 1)) + return(1); bp->bp_installed = 0; } return(0); Index: linux-2.6.24-rc2/arch/x86/kdb/kdbasupport_32.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdbasupport_32.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdbasupport_32.c @@ -82,7 +82,7 @@ kdba_putdr(int regnum, kdb_machreg_t con } } -static kdb_machreg_t +kdb_machreg_t kdba_getdr(int regnum) { kdb_machreg_t contents = 0; @@ -142,40 +142,42 @@ kdba_putdr7(kdb_machreg_t contents) void kdba_installdbreg(kdb_bp_t *bp) { + int cpu = smp_processor_id(); + kdb_machreg_t dr7; dr7 = kdba_getdr7(); - kdba_putdr(bp->bp_hard->bph_reg, bp->bp_addr); + kdba_putdr(bp->bp_hard[cpu]->bph_reg, bp->bp_addr); dr7 |= DR7_GE; if (cpu_has_de) set_in_cr4(X86_CR4_DE); - switch (bp->bp_hard->bph_reg){ + switch (bp->bp_hard[cpu]->bph_reg){ case 0: - DR7_RW0SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN0SET(dr7,bp->bp_hard->bph_length); + DR7_RW0SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN0SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G0SET(dr7); break; case 1: - DR7_RW1SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN1SET(dr7,bp->bp_hard->bph_length); + DR7_RW1SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN1SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G1SET(dr7); break; case 2: - DR7_RW2SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN2SET(dr7,bp->bp_hard->bph_length); + DR7_RW2SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN2SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G2SET(dr7); break; case 3: - DR7_RW3SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN3SET(dr7,bp->bp_hard->bph_length); + DR7_RW3SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN3SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G3SET(dr7); break; default: kdb_printf("kdb: Bad debug register!! %ld\n", - bp->bp_hard->bph_reg); + bp->bp_hard[cpu]->bph_reg); break; } @@ -188,11 +190,12 @@ kdba_removedbreg(kdb_bp_t *bp) { int regnum; kdb_machreg_t dr7; + int cpu = smp_processor_id(); - if (!bp->bp_hard) + if (!bp->bp_hard[cpu]) return; - regnum = bp->bp_hard->bph_reg; + regnum = bp->bp_hard[cpu]->bph_reg; dr7 = kdba_getdr7(); Index: linux-2.6.24-rc2/include/linux/kdbprivate.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h +++ linux-2.6.24-rc2/include/linux/kdbprivate.h @@ -204,7 +204,7 @@ typedef struct _kdb_bp { int bp_cpu; /* Cpu # (if bp_global == 0) */ kdbhard_bp_t bp_template; /* Hardware breakpoint template */ - kdbhard_bp_t *bp_hard; /* Hardware breakpoint structure */ + kdbhard_bp_t* bp_hard[NR_CPUS]; /* Hardware breakpoint structure */ int bp_adjust; /* Adjustment to PC for real instruction */ } kdb_bp_t; @@ -219,8 +219,8 @@ extern kdb_bp_t kdb_breakpoints[/* KDB_M */ extern void kdba_initbp(void); extern void kdba_printbp(kdb_bp_t *); -extern kdbhard_bp_t *kdba_allocbp(kdbhard_bp_t *, int *); -extern void kdba_freebp(kdbhard_bp_t *); +extern void kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp); +extern void kdba_free_hwbp(kdb_bp_t *bp); extern int kdba_parsebp(int, const char**, int *, kdb_bp_t*); extern char *kdba_bptype(kdbhard_bp_t *); extern void kdba_setsinglestep(struct pt_regs *); Index: linux-2.6.24-rc2/kdb/kdb_bp.c =================================================================== --- linux-2.6.24-rc2.orig/kdb/kdb_bp.c +++ linux-2.6.24-rc2/kdb/kdb_bp.c @@ -54,8 +54,9 @@ kdb_bp_install_global(struct pt_regs *re kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n", i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global); } + /* Hw breakpoints local or global are installed in kdb_bp_install_local() */ if (kdb_breakpoints[i].bp_enabled - && kdb_breakpoints[i].bp_global) { + && (kdb_breakpoints[i].bp_global && !kdb_breakpoints[i].bp_hardtype)) { kdba_installbp(regs, &kdb_breakpoints[i]); } } @@ -86,18 +87,32 @@ void kdb_bp_install_local(struct pt_regs *regs) { int i; + int do_install; for(i=0; i=0; i--) { + do_remove = 0; + if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_remove_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n", i, kdb_breakpoints[i].bp_enabled, kdb_breakpoints[i].bp_global, smp_processor_id(), kdb_breakpoints[i].bp_cpu); } - if (kdb_breakpoints[i].bp_enabled - && kdb_breakpoints[i].bp_cpu == smp_processor_id() - && !kdb_breakpoints[i].bp_global){ - kdba_removebp(&kdb_breakpoints[i]); + + if (!kdb_breakpoints[i].bp_enabled) + continue; + + if (kdb_breakpoints[i].bp_hardtype){ + if((kdb_breakpoints[i].bp_cpu == smp_processor_id()) || + kdb_breakpoints[i].bp_global) + do_remove = 1; + } else { + if(kdb_breakpoints[i].bp_cpu == smp_processor_id() && + !kdb_breakpoints[i].bp_global) + do_remove = 1; } + + if (do_remove) + kdba_removebp(&kdb_breakpoints[i]); } } @@ -332,12 +362,13 @@ kdb_bp(int argc, const char **argv) * attempt to allocate a hardware register for it. */ if (!bp->bp_template.bph_free) { - bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag); - if (diag) { + kdba_alloc_hwbp(bp, &diag); + if (diag){ bp->bp_enabled = 0; + bp->bp_hardtype = 0; + kdba_free_hwbp(bp); return diag; } - bp->bp_hardtype = 1; } kdb_printbp(bp, bpno); @@ -432,11 +463,8 @@ kdb_bc(int argc, const char **argv) switch (cmd) { case KDBCMD_BC: - if (bp->bp_hardtype) { - kdba_freebp(bp->bp_hard); - bp->bp_hard = NULL; - bp->bp_hardtype = 0; - } + if (bp->bp_hardtype) + kdba_free_hwbp(bp); bp->bp_enabled = 0; bp->bp_global = 0; @@ -455,12 +483,14 @@ kdb_bc(int argc, const char **argv) */ if (!bp->bp_template.bph_free && !bp->bp_hardtype) { - bp->bp_hard = kdba_allocbp(&bp->bp_template, &diag); - if (diag) { + kdba_alloc_hwbp(bp, &diag); + if (diag){ bp->bp_enabled = 0; + bp->bp_hardtype = 0; + kdba_free_hwbp(bp); return diag; } - bp->bp_hardtype = 1; + } bp->bp_enabled = 1; @@ -479,11 +509,9 @@ kdb_bc(int argc, const char **argv) * give up the hardware register which is allocated * to it. */ - if (bp->bp_hardtype) { - kdba_freebp(bp->bp_hard); - bp->bp_hard = NULL; - bp->bp_hardtype = 0; - } + + if (bp->bp_hardtype) + kdba_free_hwbp(bp); bp->bp_enabled = 0; Index: linux-2.6.24-rc2/include/asm-x86/kdbprivate_32.h =================================================================== --- linux-2.6.24-rc2.orig/include/asm-x86/kdbprivate_32.h +++ linux-2.6.24-rc2/include/asm-x86/kdbprivate_32.h @@ -45,6 +45,7 @@ typedef struct _kdbhard_bp { unsigned int bph_write:1; /* Write Data breakpoint */ unsigned int bph_mode:2; /* 0=inst, 1=write, 2=io, 3=read */ unsigned int bph_length:2; /* 0=1, 1=2, 2=BAD, 3=4 (bytes) */ + unsigned int bph_installed; /* flag: hw bp is installed */ } kdbhard_bp_t; #define IA32_BREAKPOINT_INSTRUCTION 0xcc Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_64.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_bp_64.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_bp_64.c @@ -22,10 +22,10 @@ static char *kdba_rwtypes[] = { "Instruc /* * Table describing processor architecture hardware - * breakpoint registers. + * breakpoint registers for every CPU. */ -kdbhard_bp_t kdb_hardbreaks[KDB_MAXHARDBPT]; +static kdbhard_bp_t kdb_hardbreaks[NR_CPUS][KDB_MAXHARDBPT]; /* * kdba_db_trap @@ -75,6 +75,7 @@ kdba_db_trap(struct pt_regs *regs, int e int i; kdb_dbtrap_t rv = KDB_DB_BPT; kdb_bp_t *bp; + int cpu = smp_processor_id(); if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; @@ -103,8 +104,12 @@ kdba_db_trap(struct pt_regs *regs, int e kdb_printf("bp for this cpu\n"); if (bp->bp_delayed) { bp->bp_delayed = 0; - if (KDB_DEBUG(BP)) + if (KDB_DEBUG(BP)){ + /* Can't be hw breakpoint */ + if (bp->bp_hardtype) + kdb_printf("kdb: Error - hw bp delayed\n"); kdb_printf("kdba_installbp\n"); + } kdba_installbp(regs, bp); if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; @@ -211,8 +216,8 @@ handle: for(i=0, bp=kdb_breakpoints; ibp_free) && (bp->bp_global || bp->bp_cpu == smp_processor_id()) - && (bp->bp_hard) - && (bp->bp_hard->bph_reg == reg)) { + && (bp->bp_hard[cpu]) + && (bp->bp_hard[cpu]->bph_reg == reg)) { /* * Hit this breakpoint. */ @@ -437,12 +442,18 @@ kdba_printbpreg(kdbhard_bp_t *bph) void kdba_printbp(kdb_bp_t *bp) { + int cpu; + kdb_printf("\n is enabled"); if (bp->bp_hardtype) { - kdba_printbpreg(bp->bp_hard); - if (bp->bp_hard->bph_mode != 0) { + if (bp->bp_global) + cpu = smp_processor_id(); + else + cpu = bp->bp_cpu; + kdba_printbpreg(bp->bp_hard[cpu]); + if (bp->bp_hard[cpu]->bph_mode != 0) { kdb_printf(" for %d bytes", - bp->bp_hard->bph_length+1); + bp->bp_hard[cpu]->bph_length+1); } } } @@ -555,7 +566,7 @@ kdba_parsebp(int argc, const char **argv /* * kdba_allocbp * - * Associate a hardware register with a breakpoint. + * Allocate hw register for bp on specific CPU * * Parameters: * None. @@ -569,13 +580,14 @@ kdba_parsebp(int argc, const char **argv * Remarks: */ -kdbhard_bp_t * -kdba_allocbp(kdbhard_bp_t *bph, int *diagp) +static kdbhard_bp_t * +kdba_allocbp(kdbhard_bp_t *bph, int *diagp, unsigned int cpu) { int i; kdbhard_bp_t *newbph; - for(i=0,newbph=kdb_hardbreaks; i < KDB_MAXHARDBPT; i++, newbph++) { + for(i=0; i < KDB_MAXHARDBPT; i++) { + newbph=&(kdb_hardbreaks[cpu][i]); if (newbph->bph_free) { break; } @@ -607,9 +619,49 @@ kdba_allocbp(kdbhard_bp_t *bph, int *dia } /* + * kdba_alloc_hwbp + * + * Associate a hardware registers with a breakpoint. + * If hw bp is global hw registers descriptor will be allocated + * on every CPU. + * + * Parameters: + * bp - hardware bp + * diagp - pointer to variable that will store error when + * function complete + * Outputs: + * None. + * Returns: + * None + * Locking: + * None. + * Remarks: + * Should be called with correct bp->bp_template + */ + +void +kdba_alloc_hwbp(kdb_bp_t *bp, int *diagp) +{ + int i; + + if (bp->bp_global){ + for (i = 0; i < NR_CPUS; ++i) { + if (!cpu_online(i)) + continue; + bp->bp_hard[i] = kdba_allocbp(&bp->bp_template, diagp, i); + if (*diagp) + break; + } + } else { + bp->bp_hard[bp->bp_cpu] = kdba_allocbp(&bp->bp_template, diagp, bp->bp_cpu); + } + bp->bp_hardtype = 1; +} + +/* * kdba_freebp * - * Deallocate a hardware breakpoint + * Deallocate hw registers descriptor for bp on specific CPU * * Parameters: * None. @@ -622,13 +674,57 @@ kdba_allocbp(kdbhard_bp_t *bph, int *dia * Remarks: */ -void +static void kdba_freebp(kdbhard_bp_t *bph) { bph->bph_free = 1; } /* + * kdba_free_hwbp + * + * Frees allocated hw registers descriptors for bp. + * If hw bp is global, hw registers descriptors will be freed + * on every CPU. + * + * Parameters: + * bp - hardware bp + * Outputs: + * None. + * Returns: + * None + * Locking: + * None. + * Remarks: + * Should be called with correct bp->bp_template + */ + +void +kdba_free_hwbp(kdb_bp_t *bp) +{ + int i; + + /* When kernel enters KDB, first, all local bps + * are removed, so here we don't need to clear + * debug registers. + */ + + if (bp->bp_global){ + for (i = 0; i < NR_CPUS; ++i) { + if (!cpu_online(i)) + continue; + if (bp->bp_hard[i]) + kdba_freebp(bp->bp_hard[i]); + bp->bp_hard[i] = 0; + } + } else { + kdba_freebp(bp->bp_hard[bp->bp_cpu]); + bp->bp_hard[bp->bp_cpu] = NULL; + } + bp->bp_hardtype = 0; +} + +/* * kdba_initbp * * Initialize the breakpoint table for the hardware breakpoint @@ -652,7 +748,7 @@ kdba_freebp(kdbhard_bp_t *bph) void kdba_initbp(void) { - int i; + int i,j; kdbhard_bp_t *bph; /* @@ -661,9 +757,15 @@ kdba_initbp(void) memset(kdb_hardbreaks, '\0', sizeof(kdb_hardbreaks)); - for(i=0,bph=kdb_hardbreaks; ibph_reg = i; - bph->bph_free = 1; + for (i = 0; i < NR_CPUS; ++i) { + /* Called early so we don't know actual + * ammount of CPUs + */ + for(j=0; j < KDB_MAXHARDBPT; j++) { + bph=&(kdb_hardbreaks[i][j]); + bph->bph_reg = j; + bph->bph_free = 1; + } } } @@ -695,6 +797,8 @@ kdba_initbp(void) int kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp) { + int cpu = smp_processor_id(); + /* * Install the breakpoint, if it is not already installed. */ @@ -704,15 +808,27 @@ kdba_installbp(struct pt_regs *regs, kdb } if (!KDB_STATE(SSBPT)) bp->bp_delay = 0; - if (!bp->bp_installed) { - if (bp->bp_hardtype) { + + if (bp->bp_hardtype) { + if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){ + kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n"); + } + + if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){ + kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n"); + return 1; + } + + if (!bp->bp_hard[cpu]->bph_installed){ kdba_installdbreg(bp); - bp->bp_installed = 1; + bp->bp_hard[cpu]->bph_installed = 1; if (KDB_DEBUG(BP)) { kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", - bp->bp_hard->bph_reg, bp->bp_addr); + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); } - } else if (bp->bp_delay) { + } + } else if (!bp->bp_installed) { + if (bp->bp_delay) { if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp delayed bp\n"); kdba_handle_bp(regs, bp); @@ -750,6 +866,8 @@ kdba_installbp(struct pt_regs *regs, kdb int kdba_removebp(kdb_bp_t *bp) { + int cpu = smp_processor_id(); + /* * For hardware breakpoints, remove it from the active register, * for software breakpoints, restore the instruction stream. @@ -757,20 +875,36 @@ kdba_removebp(kdb_bp_t *bp) if (KDB_DEBUG(BP)) { kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed); } - if (bp->bp_installed) { - if (bp->bp_hardtype) { + + if (bp->bp_hardtype) { + if (KDB_DEBUG(BP) && !bp->bp_global && cpu != bp->bp_cpu){ + kdb_printf("kdba_removebp: cpu != bp->bp_cpu for local hw bp\n"); + } + + if (KDB_DEBUG(BP) && !bp->bp_hard[cpu]){ + kdb_printf("kdba_removebp: Error - bp_hard[smp_processor_id()] is emply\n"); + return 1; + } + + if (KDB_DEBUG(BP)) { + kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n", + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); + } + + if (bp->bp_hard[cpu]->bph_installed){ if (KDB_DEBUG(BP)) { - kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n", - bp->bp_hard->bph_reg, bp->bp_addr); + kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", + bp->bp_hard[cpu]->bph_reg, bp->bp_addr); } kdba_removedbreg(bp); - } else { - if (KDB_DEBUG(BP)) - kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n", - bp->bp_inst, bp->bp_addr); - if (kdb_putword(bp->bp_addr, bp->bp_inst, 1)) - return(1); + bp->bp_hard[cpu]->bph_installed = 0; } + } else if (bp->bp_installed) { + if (KDB_DEBUG(BP)) + kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n", + bp->bp_inst, bp->bp_addr); + if (kdb_putword(bp->bp_addr, bp->bp_inst, 1)) + return(1); bp->bp_installed = 0; } return(0); Index: linux-2.6.24-rc2/arch/x86/kdb/kdbasupport_64.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdbasupport_64.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdbasupport_64.c @@ -55,40 +55,42 @@ kdba_putdr7(kdb_machreg_t contents) void kdba_installdbreg(kdb_bp_t *bp) { + int cpu = smp_processor_id(); + kdb_machreg_t dr7; dr7 = kdba_getdr7(); - kdba_putdr(bp->bp_hard->bph_reg, bp->bp_addr); + kdba_putdr(bp->bp_hard[cpu]->bph_reg, bp->bp_addr); dr7 |= DR7_GE; if (cpu_has_de) set_in_cr4(X86_CR4_DE); - switch (bp->bp_hard->bph_reg){ + switch (bp->bp_hard[cpu]->bph_reg){ case 0: - DR7_RW0SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN0SET(dr7,bp->bp_hard->bph_length); + DR7_RW0SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN0SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G0SET(dr7); break; case 1: - DR7_RW1SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN1SET(dr7,bp->bp_hard->bph_length); + DR7_RW1SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN1SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G1SET(dr7); break; case 2: - DR7_RW2SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN2SET(dr7,bp->bp_hard->bph_length); + DR7_RW2SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN2SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G2SET(dr7); break; case 3: - DR7_RW3SET(dr7,bp->bp_hard->bph_mode); - DR7_LEN3SET(dr7,bp->bp_hard->bph_length); + DR7_RW3SET(dr7,bp->bp_hard[cpu]->bph_mode); + DR7_LEN3SET(dr7,bp->bp_hard[cpu]->bph_length); DR7_G3SET(dr7); break; default: kdb_printf("kdb: Bad debug register!! %ld\n", - bp->bp_hard->bph_reg); + bp->bp_hard[cpu]->bph_reg); break; } @@ -101,11 +103,12 @@ kdba_removedbreg(kdb_bp_t *bp) { int regnum; kdb_machreg_t dr7; + int cpu = smp_processor_id(); - if (!bp->bp_hard) + if (!bp->bp_hard[cpu]) return; - regnum = bp->bp_hard->bph_reg; + regnum = bp->bp_hard[cpu]->bph_reg; dr7 = kdba_getdr7(); Index: linux-2.6.24-rc2/include/asm-x86/kdbprivate_64.h =================================================================== --- linux-2.6.24-rc2.orig/include/asm-x86/kdbprivate_64.h +++ linux-2.6.24-rc2/include/asm-x86/kdbprivate_64.h @@ -45,10 +45,9 @@ typedef struct _kdbhard_bp { unsigned int bph_write:1; /* Write Data breakpoint */ unsigned int bph_mode:2; /* 0=inst, 1=write, 2=io, 3=read */ unsigned int bph_length:2; /* 0=1, 1=2, 2=BAD, 3=4 (bytes) */ + unsigned int bph_installed; /* flag: hw bp is installed */ } kdbhard_bp_t; -extern kdbhard_bp_t kdb_hardbreaks[/* KDB_MAXHARDBPT */]; - #define IA32_BREAKPOINT_INSTRUCTION 0xcc #define DR6_BT 0x00008000 --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From randy.dunlap@verizon.net Fri Nov 30 10:19:29 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 10:19:38 -0800 (PST) Received: from vms042pub.verizon.net (vms042pub.verizon.net [206.46.252.42]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUIJS1K031690 for ; Fri, 30 Nov 2007 10:19:29 -0800 Received: from midway.site ([71.117.233.180]) by vms042.mailsrvcs.net (Sun Java System Messaging Server 6.2-6.01 (built Apr 3 2006)) with ESMTPA id <0JSB00FICXG1Y2C1@vms042.mailsrvcs.net> for kdb@oss.sgi.com; Fri, 30 Nov 2007 11:19:14 -0600 (CST) Date: Fri, 30 Nov 2007 09:19:12 -0800 From: "Randy.Dunlap" Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI In-reply-to: <200711301700.lAUH0o8l10107350@kluge.engr.sgi.com> To: Aaron Young Cc: kbaidarov@ru.mvista.com (Konstantin Baydarov), ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Message-id: <20071130091912.e89d42ac.randy.dunlap@verizon.net> Organization: YPO4 MIME-version: 1.0 X-Mailer: Sylpheed 2.4.7 (GTK+ 2.8.10; x86_64-unknown-linux-gnu) Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit References: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> <200711301700.lAUH0o8l10107350@kluge.engr.sgi.com> X-archive-position: 1305 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: randy.dunlap@verizon.net Precedence: bulk X-list: kdb On Fri, 30 Nov 2007 09:00:50 -0800 (PST) Aaron Young wrote: > > > Another thing, I think we need to update these files: > > arch/ia64/Kconfig.debug > arch/x86/Kconfig.debug > > to change this line: > depends on KDB && USB_OHCI_HCD > > to: > > depends on KDB && USB_OHCI_HCD && USB_UHCI_HCD && USB_EHCI_HCD I don't have the complete patch in front of me, but why would all 3 of those HCDs be needed? I would expect it to be more like depends on KDB && (USB_OHCI_HCD || USB_UHCI_HCD) and even omit the EHCI_HCD part since it is only for high-speed devices and I've never seen a keyboard that is a high-speed USB device. (or maybe I'm way out of context...) > > Jay? --- ~Randy --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From kbaidarov@ru.mvista.com Fri Nov 30 11:46:24 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 11:46:33 -0800 (PST) Received: from mail.dev.rtsoft.ru (rtsoft2.corbina.net [85.21.88.2] (may be forged)) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with SMTP id lAUJkLCm008732 for ; Fri, 30 Nov 2007 11:46:23 -0800 Received: (qmail 890 invoked from network); 30 Nov 2007 19:46:30 -0000 Received: from unknown (HELO localhost.localdomain) (192.168.1.195) by mail.dev.rtsoft.ru with SMTP; 30 Nov 2007 19:46:30 -0000 Date: Fri, 30 Nov 2007 22:46:28 +0300 From: Konstantin Baydarov To: Aaron Young Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI Message-ID: <20071130224628.51152a03@localhost.localdomain> In-Reply-To: <200711301643.lAUGh7ig10071434@kluge.engr.sgi.com> References: <200711301552.lAUFqxdA9993872@kluge.engr.sgi.com> <200711301643.lAUGh7ig10071434@kluge.engr.sgi.com> X-Mailer: Sylpheed-Claws 2.6.0 (GTK+ 2.8.19; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-archive-position: 1306 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: kbaidarov@ru.mvista.com Precedence: bulk X-list: kdb On Fri, 30 Nov 2007 08:43:07 -0800 (PST) Aaron Young wrote: > > > > Also, should kdb_uhci_keyboard_chech_uhci_qh() be > kdb_uhci_keyboard_check_uhci_qh()? - Changed. > > > > > > > > > > Looking better! More comments: > > > > 1. I don't understand the need for the call to > > kdb_uhci_keyboard_clear(). It's only called if > > kdb_usb_keyboard_attach() fails and in that case we > > didn't add the urb to kdb_usb_kbds[]. So, I don't > > see the need to clear it out of kdb_usb_kbds[]... > > (I'm probably missing something here). - Now I call kdb_uhci_keyboard_clear() if usb_submit_urb() failed, that is called after kdb_usb_keyboard_attach(). > > > > 2. I probably would have made kdb_uhci_submit_urb() return > > the newly created kdb_urb (extra arg) on success and not call > > kdb_usb_keyboard_attach() directly from within. Then you can > > just make a single call to kdb_usb_keyboard_attach() for all three > > cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not > > a *BIG* deal... - We should first fill kdb_usb_kbds[] before call of usb_submit_urb() because uhci_urb_enqueue() checks kdb_usb_kbds[] to find out if KDB URB is enqueued. So kdb_usb_keyboard_attach() should be called in the "middle" of the function kdb_uhci_submit_urb(). > > > > 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise > > it will result in compile errors on ia64. i.e. > > kdb_usb_keyboard_attach() will have a number of args mismatch and > > all the routines you added to kdba_io_32.c and kdba_io_64.c will > > not be there. - Can't find any ia64 file... > > > > 4. You have the comment "/* found a free array index */" in several > > of the new kdba_io*.c routines when it really means you found > > a "match". - Fixed. > > > > 5. I just submitted another patch on Wed (Nov. 28th). That will > > conflict with this one again. Sorry - should be my last patch. - Done. > > > > > > Does hotplug/hotunplug of the keyboards work? > > Does it correctly remove the KDB URBs on hotunplug? - kdb_usb_keyboard_detach() is never called on my PC. So I tested only 1 case: attaching keyboard after kernel boot - works OK. > > > > Thanks, > > > > -Aaron > Index: linux-2.6.24-rc2/drivers/usb/host/uhci-q.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-q.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-q.c @@ -25,6 +25,18 @@ * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort */ +#ifdef CONFIG_KDB_USB +/* KDB HID QH, managed by KDB code */ +extern int kdb_uhci_keyboard_chech_uhci_qh(struct uhci_qh *qh); +extern int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh); +extern struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb); +extern int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event); +extern int kdb_uhci_keyboard_get_hid_event(struct urb *urb); +extern int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event); +extern int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh); +#endif + + static void uhci_set_next_interrupt(struct uhci_hcd *uhci) { if (uhci->is_stopped) @@ -292,6 +304,58 @@ static struct uhci_qh *uhci_alloc_qh(str return qh; } +#ifdef CONFIG_KDB_USB +/* + * Same as uhci_alloc_qh execpt it doesn't change to hep->hcpriv + */ +static struct uhci_qh *kdb_uhci_alloc_qh(struct uhci_hcd *uhci, + struct usb_device *udev, struct usb_host_endpoint *hep) +{ + dma_addr_t dma_handle; + struct uhci_qh *qh; + + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + if (!qh) + return NULL; + + memset(qh, 0, sizeof(*qh)); + qh->dma_handle = dma_handle; + + qh->element = UHCI_PTR_TERM; + qh->link = UHCI_PTR_TERM; + + INIT_LIST_HEAD(&qh->queue); + INIT_LIST_HEAD(&qh->node); + + if (udev) { /* Normal QH */ + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (qh->type != USB_ENDPOINT_XFER_ISOC) { + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; + } + } + qh->state = QH_STATE_IDLE; + qh->hep = hep; + qh->udev = udev; + + if (qh->type == USB_ENDPOINT_XFER_INT || + qh->type == USB_ENDPOINT_XFER_ISOC) + qh->load = usb_calc_bus_time(udev->speed, + usb_endpoint_dir_in(&hep->desc), + qh->type == USB_ENDPOINT_XFER_ISOC, + le16_to_cpu(hep->desc.wMaxPacketSize)) + / 1000 + 1; + + } else { /* Skeleton QH */ + qh->state = QH_STATE_ACTIVE; + qh->type = -1; + } + return qh; +} +#endif + static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); @@ -1399,6 +1463,20 @@ static int uhci_urb_enqueue(struct usb_h if (!urbp) goto done; +#ifdef CONFIG_KDB_USB + /* Always allocate new QH for KDB URB. + * KDB HQ will be managed by KDB poll code not by + * UHCI HCD Driver. + */ + if (kdb_uhci_keyboard_urb(urb) != -1){ + /* KDB urb will be enqued only once */ + kdb_uhci_keyboard_set_qh(urb, NULL); + qh = kdb_uhci_alloc_qh(uhci, urb->dev, urb->ep); + if (!qh) + goto err_no_qh; + kdb_uhci_keyboard_set_qh(urb, qh); + } else +#endif if (urb->ep->hcpriv) qh = urb->ep->hcpriv; else { @@ -1648,6 +1726,13 @@ static int uhci_advance_check(struct uhc int ret = 1; unsigned status; +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1){ + ret = 0; + goto done; + } +#endif if (qh->type == USB_ENDPOINT_XFER_ISOC) goto done; @@ -1740,6 +1825,11 @@ rescan: uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, node); +#ifdef CONFIG_KDB_USB + /* Don't manage KDB QH */ + if(kdb_uhci_keyboard_chech_uhci_qh(qh) != -1) + continue; +#endif if (uhci_advance_check(uhci, qh)) { uhci_scan_qh(uhci, qh); if (qh->state == QH_STATE_ACTIVE) { @@ -1766,3 +1856,76 @@ rescan: else uhci_set_next_interrupt(uhci); } + +#ifdef CONFIG_KDB_USB +/* + * Activate KDB UHCI QH, called by KDB poll code. + */ +static void kdb_activate_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp; + struct uhci_td *td; + __le32 status, token; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + + list_for_each_entry(td, &urbp->td_list, list){ + status = td->status; + token = td->token; + barrier(); + /* Clear Status and ActLen */ + status &= cpu_to_le32(0xff000000); + /* Make TD Active */ + status |= cpu_to_le32(TD_CTRL_ACTIVE); + /* Clear TD Interrupt */ + status &= cpu_to_le32(~TD_CTRL_IOC); + /* Toggle Data Sycronization Bit */ + if (token & cpu_to_le32(TD_TOKEN_TOGGLE)) + token &= cpu_to_le32(~TD_TOKEN_TOGGLE); + else + token |= cpu_to_le32(TD_TOKEN_TOGGLE); + + td->token = token; + td->status = status; + barrier(); + } + /* Activate KDB UHCI Keyboard HID QH */ + td = list_entry(urbp->td_list.next, struct uhci_td, list); + qh->element = LINK_TO_TD(td); + barrier(); +} + +/* + * Called when KDB finishes process key press/release event. + */ +static void +kdb_uhci_urb_complete (struct urb *urb) +{ + if (!kdb_uhci_keyboard_get_hid_event(urb)) + return; + + /* Activate KDB TD */ + kdb_activate_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); + kdb_uhci_keyboard_set_hid_event(urb, 0); +} + +/* + * Check if state of KDB URB changed (key was pressed/released). + */ +static int uhci_check_kdb_uhci_qh(struct uhci_qh *qh) +{ + struct urb_priv *urbp = NULL; + struct uhci_td *td; + unsigned status; + + urbp = list_entry(qh->queue.next, struct urb_priv, node); + td = list_entry(urbp->td_list.next, struct uhci_td, list); + status = td_status(td); + if (!(status & TD_CTRL_ACTIVE)){ + /* We're okay, the queue has advanced */ + kdb_uhci_keyboard_set_hid_event_qh(qh, 1); + return 0; + } + return -1; +} +#endif Index: linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/hid/usbhid/hid-core.c +++ linux-2.6.24-rc2/drivers/hid/usbhid/hid-core.c @@ -969,6 +969,87 @@ static void hid_disconnect(struct usb_in hid_free_device(hid); } +#ifdef CONFIG_KDB_USB +/* Only 1 UHCI Keyboard supported */ +static inline void kdb_usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete_fn, + void *context, + int interval) +{ + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete_fn; + urb->context = context; + urb->interval = interval; + urb->start_frame = -1; +} + +static int kdb_uhci_submit_urb(struct usb_interface *intf, unsigned int usbhid_bufsize, struct urb *hid_inurb) +{ + struct urb *kdb_urb = NULL; + unsigned char *kdb_buffer; + dma_addr_t uhci_inbuf_dma; + int ret = -1; + extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + + if (!(kdb_buffer = usb_buffer_alloc(hid_inurb->dev, + usbhid_bufsize, GFP_ATOMIC, + &uhci_inbuf_dma))) + goto out; + + if (!(kdb_urb = usb_alloc_urb(0, GFP_KERNEL))) + goto out; + + kdb_usb_fill_int_urb(kdb_urb, + hid_inurb->dev, + hid_inurb->pipe, + kdb_buffer, + hid_inurb->transfer_buffer_length, + hid_inurb->complete, + hid_inurb->context, + hid_inurb->interval + ); + + (kdb_urb)->transfer_dma = uhci_inbuf_dma; + (kdb_urb)->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + ret = kdb_usb_keyboard_attach(kdb_urb, kdb_buffer, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf)), hid_inurb); + + if (ret) + goto out; + + if (usb_submit_urb(kdb_urb, GFP_ATOMIC)){ + kdb_uhci_keyboard_clear(kdb_urb); + goto out; + } + + ret = 0; + return ret; +out: + /* Some Error Cleanup */ + printk("KDB: Error, UHCI Keyboard HID won't work!\n"); + + if (kdb_buffer) + usb_buffer_free(hid_inurb->dev, + usbhid_bufsize, kdb_buffer, + uhci_inbuf_dma); + + if (kdb_urb) + usb_free_urb(kdb_urb); + + return ret; +} +#endif + static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct hid_device *hid; @@ -1045,8 +1126,15 @@ static int hid_probe(struct usb_interfac int ret; struct usbhid_device *usbhid = hid->driver_data; extern void * usb_hcd_get_kdb_poll_func(struct usb_device *udev); - ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, - usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf))); + extern void * usb_hcd_get_kdb_completion_func(struct usb_device *udev); + extern int usb_hcd_check_uhci(struct usb_device *udev); + + if (usb_hcd_check_uhci(interface_to_usbdev(intf))) + ret = kdb_uhci_submit_urb(intf, usbhid->bufsize, usbhid->urbin); + else + ret = kdb_usb_keyboard_attach(usbhid->urbin, usbhid->inbuf, + usb_hcd_get_kdb_poll_func(interface_to_usbdev(intf)), + usb_hcd_get_kdb_completion_func(interface_to_usbdev(intf)), NULL); if (ret == -1) printk(": FAILED to register keyboard (%s) " Index: linux-2.6.24-rc2/include/linux/kdb.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdb.h +++ linux-2.6.24-rc2/include/linux/kdb.h @@ -143,9 +143,17 @@ extern void smp_kdb_stop(void); #include -extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func); +extern int kdb_uhci_keyboard_urb(struct urb *urb); +extern int kdb_uhci_keyboard_clear(struct urb *urb); +extern int kdb_usb_keyboard_alloc(void); + +extern int kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func, void *compl_func, struct urb *hid_urb); extern int kdb_usb_keyboard_detach(struct urb *urb); +extern int +kdb_usb_uhci_keyboard_attach(struct urb *urb, unsigned int usbhid_bufsize, + void *poll_func, void *compl_func); + #endif /* CONFIG_KDB_USB */ static inline Index: linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/host/uhci-hcd.c +++ linux-2.6.24-rc2/drivers/usb/host/uhci-hcd.c @@ -50,6 +50,10 @@ #include "uhci-hcd.h" #include "pci-quirks.h" +#ifdef CONFIG_KDB_USB +#include +#endif + /* * Version Information */ @@ -430,6 +434,17 @@ static irqreturn_t uhci_irq(struct usb_h return IRQ_HANDLED; } +#ifdef CONFIG_KDB_USB +static int +uhci_kdb_poll_char(struct urb *urb) +{ + if (!urb) /* can happen if no keyboard attached */ + return -1; + + return uhci_check_kdb_uhci_qh(kdb_uhci_keyboard_get_qh(urb)); +} +#endif + /* * Store the current frame number in uhci->frame_number if the controller * is runnning. Expand from 11 bits (of which we use only 10) to a @@ -888,6 +903,10 @@ static const struct hc_driver uhci_drive .hub_status_data = uhci_hub_status_data, .hub_control = uhci_hub_control, +#ifdef CONFIG_KDB_USB + .kdb_poll_char = uhci_kdb_poll_char, + .kdb_completion = kdb_uhci_urb_complete, +#endif }; static const struct pci_device_id uhci_pci_ids[] = { { Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_32.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_32.c @@ -55,12 +55,137 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; +/* Check if URB is managed by KDB code */ +int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); + +/* Check if UHCI QH is managed by KDB code */ +int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); + +/* Clear keyboar entry */ +int kdb_uhci_keyboard_clear(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].urb_complete = NULL; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); + +/* Set UHCI QH using URB pointer */ +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].qh = qh; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); + +/* Get UHCI QH using URB pointer */ +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].qh; + + return NULL; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); + +/* Set UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].kdb_hid_event = hid_event; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); + +/* Get UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].kdb_hid_event; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); + +/* Set UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); + +/* Get UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return kdb_usb_kbds[i].kdb_hid_event; + } + + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); + /* * kdb_usb_keyboard_attach() * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func, struct urb *hid_urb) { int i; int rc = -1; @@ -82,6 +207,8 @@ kdb_usb_keyboard_attach(struct urb *urb, kdb_usb_kbds[i].urb = urb; kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = compl_func; + kdb_usb_kbds[i].hid_urb = hid_urb; rc = 0; /* success */ @@ -112,14 +239,20 @@ kdb_usb_keyboard_detach(struct urb *urb) */ for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { - if (kdb_usb_kbds[i].urb != urb) - continue; + if (kdb_usb_kbds[i].qh) { + /* UHCI keyboard */ + if (kdb_usb_kbds[i].hid_urb != urb) + continue; + } else + if (kdb_usb_kbds[i].urb != urb) + continue; /* found it, clear the index */ kdb_usb_kbds[i].urb = NULL; kdb_usb_kbds[i].buffer = NULL; kdb_usb_kbds[i].poll_func = NULL; kdb_usb_kbds[i].caps_lock = 0; + kdb_usb_kbds[i].hid_urb = NULL; rc = 0; /* success */ @@ -142,6 +275,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int ret_key = -1, i2, j, max; + + ret = -1; if (kdb_no_usb) return -1; @@ -169,15 +305,24 @@ get_usb_char(void) if (ret < 0) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; - keycode = kdb_usb_kbds[i].buffer[2]; + keycode = kdb_usb_kbds[i].buffer[max]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } + ret_key = -1; /* A normal key is pressed, decode it */ if(keycode) @@ -189,10 +334,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret_key = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -201,31 +348,45 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; - + ret_key = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret_key = 8; + break; case 0x0F: /* TAB */ - return 9; + ret_key = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret_key = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; } } } + /* Key was pressed, return keycode */ + break; } - /* no chars were returned from any of the USB keyboards */ + for(i2=0; i2<8; i2++){ + if (kdb_usb_kbds[i2].buffer) + for(j=0; j<8; j++){ + kdb_usb_kbds[i2].buffer[j] = (char)0; + } + } + + if (kdb_usb_kbds[i].urb_complete) + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); - return -1; + return ret_key; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c =================================================================== --- linux-2.6.24-rc2.orig/arch/x86/kdb/kdba_io_64.c +++ linux-2.6.24-rc2/arch/x86/kdb/kdba_io_64.c @@ -55,12 +55,137 @@ static unsigned char kdb_usb_keycode[256 150,158,159,128,136,177,178,176,142,152,173,140 }; +/* Check if URB is managed by KDB code */ +int kdb_uhci_keyboard_urb(struct urb *urb) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].urb == urb) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_urb); + +/* Check if UHCI QH is managed by KDB code */ +int kdb_uhci_keyboard_check_uhci_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return i; + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_chech_uhci_qh); + +/* Clear keyboar entry */ +int kdb_uhci_keyboard_clear(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1){ + kdb_usb_kbds[i].urb = NULL; + kdb_usb_kbds[i].buffer = NULL; + kdb_usb_kbds[i].poll_func = NULL; + kdb_usb_kbds[i].urb_complete = NULL; + } + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_clear); + +/* Set UHCI QH using URB pointer */ +int kdb_uhci_keyboard_set_qh(struct urb *urb, struct uhci_qh *qh) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].qh = qh; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_qh); + +/* Get UHCI QH using URB pointer */ +struct uhci_qh *kdb_uhci_keyboard_get_qh(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].qh; + + return NULL; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_qh); + +/* Set UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_set_hid_event(struct urb *urb, int hid_event) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + kdb_usb_kbds[i].kdb_hid_event = hid_event; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event); + +/* Get UHCI hid_event using URB pointer */ +int kdb_uhci_keyboard_get_hid_event(struct urb *urb) +{ + int i; + + i = kdb_uhci_keyboard_urb(urb); + if (i != -1) + return kdb_usb_kbds[i].kdb_hid_event; + + return 0; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event); + +/* Set UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_set_hid_event_qh(struct uhci_qh *qh, int hid_event) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh){ + kdb_usb_kbds[i].kdb_hid_event = hid_event; + return i; + } + } + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_set_hid_event_qh); + +/* Get UHCI hid_event using UHCI QH pointer */ +int kdb_uhci_keyboard_get_hid_event_qh(struct uhci_qh *qh) +{ + int i; + + for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { + if (kdb_usb_kbds[i].urb && kdb_usb_kbds[i].qh == qh) + return kdb_usb_kbds[i].kdb_hid_event; + } + + return -1; +} +EXPORT_SYMBOL_GPL (kdb_uhci_keyboard_get_hid_event_qh); + /* * kdb_usb_keyboard_attach() * Attach a USB keyboard to kdb. */ int -kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, void *poll_func) +kdb_usb_keyboard_attach(struct urb *urb, unsigned char *buffer, + void *poll_func, void *compl_func, struct urb *hid_urb) { int i; int rc = -1; @@ -82,6 +207,8 @@ kdb_usb_keyboard_attach(struct urb *urb, kdb_usb_kbds[i].urb = urb; kdb_usb_kbds[i].buffer = buffer; kdb_usb_kbds[i].poll_func = poll_func; + kdb_usb_kbds[i].urb_complete = compl_func; + kdb_usb_kbds[i].hid_urb = hid_urb; rc = 0; /* success */ @@ -112,14 +239,20 @@ kdb_usb_keyboard_detach(struct urb *urb) */ for (i = 0; i < KDB_USB_NUM_KEYBOARDS; i++) { - if (kdb_usb_kbds[i].urb != urb) - continue; + if (kdb_usb_kbds[i].qh) { + /* UHCI keyboard */ + if (kdb_usb_kbds[i].hid_urb != urb) + continue; + } else + if (kdb_usb_kbds[i].urb != urb) + continue; /* found it, clear the index */ kdb_usb_kbds[i].urb = NULL; kdb_usb_kbds[i].buffer = NULL; kdb_usb_kbds[i].poll_func = NULL; kdb_usb_kbds[i].caps_lock = 0; + kdb_usb_kbds[i].hid_urb = NULL; rc = 0; /* success */ @@ -142,6 +275,9 @@ get_usb_char(void) int ret; unsigned char keycode, spec; extern u_short plain_map[], shift_map[], ctrl_map[]; + int ret_key = -1, i2, j, max; + + ret = -1; if (kdb_no_usb) return -1; @@ -169,15 +305,24 @@ get_usb_char(void) if (ret < 0) /* error or no characters, try the next kbd */ continue; + /* If 2 keys was pressed simultaneously, + * both keycodes will be in buffer. + * Last pressed key will be last non + * zero byte. + */ + for (j=0; j<4; j++){ + if (!kdb_usb_kbds[i].buffer[2+j]) + break; + } + /* Last pressed key */ + max = j + 1; + spec = kdb_usb_kbds[i].buffer[0]; - keycode = kdb_usb_kbds[i].buffer[2]; + keycode = kdb_usb_kbds[i].buffer[max]; kdb_usb_kbds[i].buffer[0] = (char)0; kdb_usb_kbds[i].buffer[2] = (char)0; - if(kdb_usb_kbds[i].buffer[3]) { - kdb_usb_kbds[i].buffer[3] = (char)0; - continue; - } + ret_key = -1; /* A normal key is pressed, decode it */ if(keycode) @@ -189,10 +334,12 @@ get_usb_char(void) { case 0x2: case 0x20: /* Shift */ - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; case 0x1: case 0x10: /* Ctrl */ - return ctrl_map[keycode]; + ret_key = ctrl_map[keycode]; + break; case 0x4: case 0x40: /* Alt */ break; @@ -201,31 +348,45 @@ get_usb_char(void) switch(keycode) { case 0x1C: /* Enter */ - return 13; - + ret_key = 13; + break; case 0x3A: /* Capslock */ kdb_usb_kbds[i].caps_lock = !(kdb_usb_kbds[i].caps_lock); break; case 0x0E: /* Backspace */ - return 8; + ret_key = 8; + break; case 0x0F: /* TAB */ - return 9; + ret_key = 9; + break; case 0x77: /* Pause */ break ; default: if(!kdb_usb_kbds[i].caps_lock) { - return plain_map[keycode]; + ret_key = plain_map[keycode]; + break; } else { - return shift_map[keycode]; + ret_key = shift_map[keycode]; + break; } } } + /* Key was pressed, return keycode */ + break; } - /* no chars were returned from any of the USB keyboards */ + for(i2=0; i2<8; i2++){ + if (kdb_usb_kbds[i2].buffer) + for(j=0; j<8; j++){ + kdb_usb_kbds[i2].buffer[j] = (char)0; + } + } + + if (kdb_usb_kbds[i].urb_complete) + (*kdb_usb_kbds[i].urb_complete)((struct urb *)kdb_usb_kbds[i].urb); - return -1; + return ret_key; } #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/include/linux/kdbprivate.h =================================================================== --- linux-2.6.24-rc2.orig/include/linux/kdbprivate.h +++ linux-2.6.24-rc2/include/linux/kdbprivate.h @@ -489,8 +489,12 @@ struct kdb_usb_kbd_info { struct urb *urb; /* pointer to the URB */ unsigned char *buffer; /* pointer to the kbd char buffer */ int (*poll_func)(struct urb *urb); /* poll function to retrieve chars */ + int (*urb_complete)(struct urb *urb); /* called when URB int is processed */ int poll_ret; /* return val from poll_func */ int caps_lock; /* state of the caps lock for this keyboard */ + struct uhci_qh *qh; + int kdb_hid_event; + struct urb *hid_urb; /* pointer to the HID URB */ }; #endif /* CONFIG_KDB_USB */ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.c =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.c +++ linux-2.6.24-rc2/drivers/usb/core/hcd.c @@ -1851,6 +1851,32 @@ usb_hcd_get_kdb_poll_func(struct usb_dev return NULL; } EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_poll_func); + +void * +usb_hcd_get_kdb_completion_func(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver) + return (void *)(hcd->driver->kdb_completion); + + return NULL; +} +EXPORT_SYMBOL_GPL (usb_hcd_get_kdb_completion_func); + +int +usb_hcd_check_uhci(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (hcd && hcd->driver){ + if (!(strcmp(hcd->driver->description, "uhci_hcd"))) + return 1; + } + + return 0; +} +EXPORT_SYMBOL_GPL (usb_hcd_check_uhci); #endif /* CONFIG_KDB_USB */ /*-------------------------------------------------------------------------*/ Index: linux-2.6.24-rc2/drivers/usb/core/hcd.h =================================================================== --- linux-2.6.24-rc2.orig/drivers/usb/core/hcd.h +++ linux-2.6.24-rc2/drivers/usb/core/hcd.h @@ -213,6 +213,7 @@ struct hc_driver { #ifdef CONFIG_KDB_USB /* KDB poll function for this HC */ int (*kdb_poll_char)(struct urb *urb); + void (*kdb_completion)(struct urb *urb); #endif /* CONFIG_KDB_USB */ }; --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From ayoung@engr.sgi.com Fri Nov 30 12:11:03 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 12:11:16 -0800 (PST) Received: from kluge.engr.sgi.com (kluge.engr.sgi.com [192.102.96.102]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUKB1X6011072 for ; Fri, 30 Nov 2007 12:11:03 -0800 Received: from kluge.engr.sgi.com (localhost [127.0.0.1]) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5) with ESMTP id lAUKB6K99994122; Fri, 30 Nov 2007 12:11:06 -0800 (PST) Received: (from ayoung@localhost) by kluge.engr.sgi.com (SGI-8.12.5/8.12.5/Submit) id lAUKB65B10139641; Fri, 30 Nov 2007 12:11:06 -0800 (PST) From: Aaron Young Message-Id: <200711302011.lAUKB65B10139641@kluge.engr.sgi.com> Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI To: kbaidarov@ru.mvista.com (Konstantin Baydarov) Date: Fri, 30 Nov 2007 12:11:05 -0800 (PST) Cc: ayoung@cthulhu.engr.sgi.com (Aaron Young), jlan@sgi.com (Jay Lan), kdb@oss.sgi.com In-Reply-To: <20071130224628.51152a03@localhost.localdomain> from "Konstantin Baydarov" at Nov 30, 2007 10:46:28 PM X-Mailer: ELM [version 2.5 PL6] MIME-Version: 1.0 Content-type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit X-archive-position: 1307 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: ayoung@engr.sgi.com Precedence: bulk X-list: kdb > > On Fri, 30 Nov 2007 08:43:07 -0800 (PST) > Aaron Young wrote: > > > > > > > > > > > > > Looking better! More comments: > > > > > > 1. I don't understand the need for the call to > > > kdb_uhci_keyboard_clear(). It's only called if > > > kdb_usb_keyboard_attach() fails and in that case we > > > didn't add the urb to kdb_usb_kbds[]. So, I don't > > > see the need to clear it out of kdb_usb_kbds[]... > > > (I'm probably missing something here). > - Now I call kdb_uhci_keyboard_clear() if usb_submit_urb() failed, that is called after kdb_usb_keyboard_attach(). Why not just call kdb_usb_keyboard_detach()? > > > > > > > 2. I probably would have made kdb_uhci_submit_urb() return > > > the newly created kdb_urb (extra arg) on success and not call > > > kdb_usb_keyboard_attach() directly from within. Then you can > > > just make a single call to kdb_usb_keyboard_attach() for all three > > > cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not > > > a *BIG* deal... > - We should first fill kdb_usb_kbds[] before call of usb_submit_urb() because uhci_urb_enqueue() checks kdb_usb_kbds[] to find out if KDB URB is enqueued. So kdb_usb_keyboard_attach() should be called in the "middle" of the function kdb_uhci_submit_urb(). OK.. > > > > > > > 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise > > > it will result in compile errors on ia64. i.e. > > > kdb_usb_keyboard_attach() will have a number of args mismatch and > > > all the routines you added to kdba_io_32.c and kdba_io_64.c will > > > not be there. > - Can't find any ia64 file... linux/arch/ia64/kdb/kdba_io.c Maybe it's part of a different KDB patch or something? Jay? > > > > > > Does hotplug/hotunplug of the keyboards work? > > > Does it correctly remove the KDB URBs on hotunplug? > - kdb_usb_keyboard_detach() is never called on my PC. So I tested only 1 case: attaching keyboard after kernel boot - works OK. Should get called out of hid_disconnect() when a keyboard is unplugged. If you are using a usb1.1 hub, it may not work - I've seen this problem with USB1.1 hub. MIght want to try plugging/unplugging the keyboard directly into the chassis port if so. BTW - do you have a USB2.0 hub? The EHCI KDB code has yet to be tested on x86 and I'd be curious if it worked or not (hope it does)... -Aaron --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. From jlan@sgi.com Fri Nov 30 12:26:45 2007 Received: with ECARTIS (v1.0.0; list kdb); Fri, 30 Nov 2007 12:26:51 -0800 (PST) Received: from cthulhu.engr.sgi.com (cthulhu.engr.sgi.com [192.26.80.2]) by oss.sgi.com (8.12.11.20060308/8.12.10/SuSE Linux 0.7) with ESMTP id lAUKQhKD016790 for ; Fri, 30 Nov 2007 12:26:45 -0800 Received: from [134.15.0.4] (mtv-vpn-sw-corp-0-4.corp.sgi.com [134.15.0.4]) by cthulhu.engr.sgi.com (8.12.10/8.12.10/SuSE Linux 0.7) with ESMTP id lAUKQmke014990; Fri, 30 Nov 2007 12:26:48 -0800 Message-ID: <47507205.2060900@sgi.com> Date: Fri, 30 Nov 2007 12:26:45 -0800 From: Jay Lan User-Agent: Thunderbird 1.5 (X11/20060317) MIME-Version: 1.0 To: Aaron Young CC: Konstantin Baydarov , Aaron Young , kdb@oss.sgi.com Subject: Re: [PATCH] Add support for USB Keyboard attached to UHCI References: <200711302011.lAUKB65B10139641@kluge.engr.sgi.com> In-Reply-To: <200711302011.lAUKB65B10139641@kluge.engr.sgi.com> X-Enigmail-Version: 0.94.0.0 Content-type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-archive-position: 1308 X-ecartis-version: Ecartis v1.0.0 Sender: kdb-bounce@oss.sgi.com Errors-to: kdb-bounce@oss.sgi.com X-original-sender: jlan@sgi.com Precedence: bulk X-list: kdb Aaron Young wrote: >> On Fri, 30 Nov 2007 08:43:07 -0800 (PST) >> Aaron Young wrote: >> >>>> >>>> >>>> Looking better! More comments: >>>> >>>> 1. I don't understand the need for the call to >>>> kdb_uhci_keyboard_clear(). It's only called if >>>> kdb_usb_keyboard_attach() fails and in that case we >>>> didn't add the urb to kdb_usb_kbds[]. So, I don't >>>> see the need to clear it out of kdb_usb_kbds[]... >>>> (I'm probably missing something here). >> - Now I call kdb_uhci_keyboard_clear() if usb_submit_urb() failed, that is called after kdb_usb_keyboard_attach(). > > Why not just call kdb_usb_keyboard_detach()? > >>>> 2. I probably would have made kdb_uhci_submit_urb() return >>>> the newly created kdb_urb (extra arg) on success and not call >>>> kdb_usb_keyboard_attach() directly from within. Then you can >>>> just make a single call to kdb_usb_keyboard_attach() for all three >>>> cases (OHCI, EHCI and UHCI) out of hid_probe(). But, not >>>> a *BIG* deal... >> - We should first fill kdb_usb_kbds[] before call of usb_submit_urb() because uhci_urb_enqueue() checks kdb_usb_kbds[] to find out if KDB URB is enqueued. So kdb_usb_keyboard_attach() should be called in the "middle" of the function kdb_uhci_submit_urb(). > > OK.. > >>>> 3. We'll have to get updates to ia64 kdba_io.c as well, otherwise >>>> it will result in compile errors on ia64. i.e. >>>> kdb_usb_keyboard_attach() will have a number of args mismatch and >>>> all the routines you added to kdba_io_32.c and kdba_io_64.c will >>>> not be there. >> - Can't find any ia64 file... > > linux/arch/ia64/kdb/kdba_io.c > > Maybe it's part of a different KDB patch or something? Jay? Hi Konstantin, It is in the ia64 kdb patch, e.g. kdb-v4.4-2.6.24-rc3-ia64-1. You can get the one corresponding to the version of your x86 and common patches. Thanks, - jay > >>>> Does hotplug/hotunplug of the keyboards work? >>>> Does it correctly remove the KDB URBs on hotunplug? >> - kdb_usb_keyboard_detach() is never called on my PC. So I tested only 1 case: attaching keyboard after kernel boot - works OK. > > Should get called out of hid_disconnect() when a > keyboard is unplugged. If you are using a usb1.1 > hub, it may not work - I've seen this problem with > USB1.1 hub. MIght want to try plugging/unplugging the keyboard > directly into the chassis port if so. > > BTW - do you have a USB2.0 hub? The EHCI KDB code has yet to > be tested on x86 and I'd be curious if it worked or not (hope it does)... > > -Aaron > --------------------------- > Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe. --------------------------- Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.