From: Christoph Hellwig <hch@infradead.org>
To: Pat Gefre <pfg@sgi.com>
Cc: linux-kernel@vger.kernel.org, matthew@wil.cx, hch@infradead.org
Subject: Re: [PATCH] 2.6.10 Altix : ioc4 serial driver support
Date: Wed, 22 Dec 2004 13:44:23 +0000 [thread overview]
Message-ID: <20041222134423.GA11750@infradead.org> (raw)
In-Reply-To: <200412220028.iBM0SB3d299993@fsgi900.americas.sgi.com>
> I cleaned this up a bit. There still are a couple of issues. One is
> that the sgiioc4 driver also "uses" the ioc4 card for ide. So the probe
> needs to "fail" so that both driver's probes will be called (is there a
> better way?). Because of that the ->remove function isn't called
> directly.
So both claim the same PCI ID? In this case you need to creat a small
shim driver that exports a pseudo-bus to the serial and ide driver using
the driver model. You must never return an error from ->probe if you
actually use that particular device.
> I still save off the pci_dev ptrs for all cards found, so I can
> register with the serial core after probe (is there a better way?).
> Should I register the driver separately for each card ? That seems a
> bit overkill.
You should register them with the serial core in ->probe.
+#include <asm/sn/ioc4.h>
Please put that header into drivers/serial/ioc4.h or if you need it from
other drivers in the future to include/linux/ioc4.h
+/* Various states/options */
+#define ENABLE_FLOW_CONTROL
+#define ENABLE_OUTPUT_INTERRUPTS
So why do you need these ifdefs? Unless there's a very good reason
kill all these conditionals.
+/* To use dynamic numbers only and not use the assigned major and minor,
+ * define the following.. */
+#define USE_DYNAMIC_MINOR 0 /* Don't rely on misc_register dynamic minor */
+static struct miscdevice misc; /* used with misc_register for dynamic */
Dito. Please kill the miscdevice code as you seem to have an assigned
number.
+/* defining this will force the driver to run in polled mode */
+//#define POLLING_FOR_CHARACTERS
Again, what's the need for these conditionals?
+/* Infinite loop detection.
+ */
+#define MAXITER 10000000
+#define SPIN(cond, success) \
+{ \
+ int spiniter = 0; \
+ success = 1; \
+ while(cond) { \
+ spiniter++; \
+ if (spiniter > MAXITER) { \
+ success = 0; \
+ break; \
+ } \
+ } \
+}
Opencoding this in the callers would make the code a lot more readable.
+static struct pci_dev *Pdevs[IOC4_NUM_CARDS];
As mentioned above this shouldn't be needed when the driver uses
proper attachment.
+/* a table to keep the card names as passed to request_region */
+static struct {
+ char c_name[20];
+} Table_o_cards[IOC4_NUM_CARDS];
Completely superflous. Just pass "ioc4_serial" as argument to request_region.
+/* Prototypes */
+static void ioc4_cb_output_lowat(struct ioc4_port *);
+static void ioc4_cb_post_ncs(struct uart_port *, int);
+static void receive_chars(struct uart_port *);
+static void handle_intr(void *arg, uint32_t sio_ir);
Please try to avoid forward-declarations where possible.
+
+/*
+ * support routines for local atomic operations.
+ */
+
+static spinlock_t local_lock;
+
+static inline unsigned int atomicClearInt(atomic_t * a, unsigned int b)
+{
+ unsigned long s;
+ unsigned int ret, new;
+
+ spin_lock_irqsave(&local_lock, s);
+ new = ret = atomic_read(a);
+ new &= ~b;
+ atomic_set(a, new);
+ spin_unlock_irqrestore(&local_lock, s);
+
+ return ret;
+}
There's only a singler caller, so better open-code it with a per-device
lock and avoid the bogus atomic_t use. It looks like using bitops.h
functions would help that code aswell.
+static inline void
+write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
+{
+ struct ioc4_mem *mem = ioc4_soft->is_ioc4_mem_addr;
+ spinlock_t *lp = &ioc4_soft->is_ir_lock;
small style nitpick: In general we try to avoid using spinlock_t pointers
just as local variables as that makes it more clear what's actually locked.
+ unsigned long s;
normally we call that variable flags. Doing so aswell here makes the
code easier to read.
+ spin_lock_irqsave(lp, s);
+
+ switch (type) {
+ case IOC4_SIO_INTR_TYPE:
+ switch (which) {
+ case IOC4_W_IES:
+ writel(val, (void *)&mem->sio_ies_ro);
The second argumnet to writeX (and readX) is actually void __iomem *,
but to see the difference you need to run sparse (from sparse.bkbits.net)
over the driver. Please store all I/O addresses in void __iomem * pointers
in your structures and avoid the cast here and in all the other places.
Remember that in 90% of the cases a cast hides a possible bug.
+ return (1);
Please avoid braces around the return values.
+ if (ioc4_revid < ioc4_revid_min) {
+ printk(KERN_WARNING
+ "IOC4 serial not supported on firmware rev %d on card %d, "
+ "please upgrade to rev %d or higher\n",
+ ioc4_revid, card_number, ioc4_revid_min);
+ return -1;
Please return meaninfull values from errno.h
+ port = (struct ioc4_port *)kmalloc(sizeof(struct ioc4_port),
+ GFP_KERNEL);
no need to cast the return value from kmalloc (dito for the other places)
+ if (pci_enable_device(pdev)) {
pci_enable_device returns an detailed error, please pass it on to the
caller.
+ /* Map in the ioc4 memory */
+ mem = (struct ioc4_mem *)pci_resource_start(pdev, 0);
You're missing an ioremap somewhere.
+ pdev->dev.driver_data = (void *)control;
please use pci_set_drvdata, the cast isn't needed here aswell.
+ control = (struct ioc4_control *)pdev->dev.driver_data;
please use pca_get_drvdata, again no need for a cast.
+ /* do the pci probing */
+ pci_register_driver(&ioc4_s_driver);
You need to check the return value from pci_register_driver.
+ if (uart_register_driver(&ioc4_uart) < 0) {
Please call uart_register_driver before calling pci_register_driver
so you can register the ports from ->probe.
+ spin_lock_irqsave(&IOC4_lock, flags);
+#ifdef POLLING_FOR_CHARACTERS
+ del_timer_sync(&IOC4_timer_list);
+#endif
del_timer_sync can sleep and must not be called inside a spinlock.
+ pci_unregister_driver(&ioc4_s_driver);
dito for pci_unregister_driver.
next prev parent reply other threads:[~2004-12-22 13:44 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-22 0:28 Pat Gefre
2004-12-22 13:44 ` Christoph Hellwig [this message]
2004-12-22 14:03 ` Russell King
2004-12-22 15:20 ` Patrick Gefre
2004-12-22 18:49 ` Russell King
2004-12-22 19:53 ` Patrick Gefre
2004-12-22 20:33 ` Matthew Wilcox
2005-01-03 14:09 ` Christoph Hellwig
2005-01-31 22:45 ` [PATCH] " Pat Gefre
2005-02-01 9:23 ` Christoph Hellwig
2005-02-02 20:36 ` Patrick Gefre
2005-02-02 21:37 ` Bartlomiej Zolnierkiewicz
2005-02-02 21:57 ` Christoph Hellwig
2005-02-07 15:58 ` Patrick Gefre
2005-02-07 16:25 ` Christoph Hellwig
2005-02-08 16:52 ` Patrick Gefre
2005-02-08 19:32 ` Patrick Gefre
2005-02-10 19:09 ` Jesse Barnes
2005-02-10 19:15 ` Christoph Hellwig
2005-02-10 21:07 ` Patrick Gefre
2005-02-17 21:55 ` Patrick Gefre
-- strict thread matches above, loose matches on Subject: below --
2004-12-16 22:24 [PATCH] 2.6.10 " Pat Gefre
2004-12-16 22:43 ` Matthew Wilcox
2004-12-16 23:15 ` Christoph Hellwig
2004-12-17 16:24 ` Matthew Wilcox
2004-12-17 22:14 ` Patrick Gefre
2004-12-18 14:51 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20041222134423.GA11750@infradead.org \
--to=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=matthew@wil.cx \
--cc=pfg@sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®