On Fri, 27 Jul 2007 18:57:20 +0200
Michael Buesch <[EMAIL PROTECTED]> wrote:

> The Sonics Silicon Backplane is a mini-bus used on
> various Broadcom chips and embedded devices.
> Devices using the SSB include b44, bcm43xx and various
> Broadcom based wireless routers.
> A b44 and bcm43xx port and a SSB based OHCI driver is available.
> 

hm, slim pickings for me here.  Nice looking code.

checkpatch finds a few coding style glitches.  Lots of 80-col violations
which you might choose ignore (comments on #defines in headers are
especially hard) but these guys:

ERROR: "foo * bar" should be "foo *bar"
#4156: FILE: drivers/ssb/ssb_private.h:119:
+extern struct ssb_bus * ssb_pci_dev_to_bus(struct pci_dev *pdev);

are worth addressing.

> ...
>
> --- /dev/null
> +++ b/drivers/ssb/driver_pcicore.c
> @@ -0,0 +1,564 @@
>
> ...
>
> +u32 pci_iobase = 0x100;
> +u32 pci_membase = SSB_PCI_DMA;

These are quite poor names for global symbols.

> +static struct resource ssb_pcicore_mem_resource = {
> +     .name   = "SSB PCIcore external memory",
> +     .start  = SSB_PCI_DMA,
> +     .end    = (u32)SSB_PCI_DMA + (u32)SSB_PCI_DMA_SZ - 1,
> +     .flags  = IORESOURCE_MEM,
> +};

start and end here are resource_size_t.  Forcing them to u32 seems
inappropriate.

> +void ssb_pcicore_init(struct ssb_pcicore *pc)

Please check that all newly-added global symbols do indeed need global scope.

> +static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
> +                             u8 address, u16 data)
> +{
> +     const u16 mdio_control = 0x128;
> +     const u16 mdio_data = 0x12C;
> +     u32 v;
> +     int i;
> +
> +     v = 0x80; /* Enable Preamble Sequence */
> +     v |= 0x2; /* MDIO Clock Divisor */
> +     pcicore_write32(pc, mdio_control, v);
> +
> +     v = (1 << 30); /* Start of Transaction */
> +     v |= (1 << 28); /* Write Transaction */
> +     v |= (1 << 17); /* Turnaround */
> +     v |= (u32)device << 22;
> +     v |= (u32)address << 18;
> +     v |= data;
> +     pcicore_write32(pc, mdio_data, v);
> +     udelay(10);

mystery udelays are usually worth a comment.

> +     for (i = 0; i < 10; i++) {
> +             v = pcicore_read32(pc, mdio_control);
> +             if (v & 0x100 /* Trans complete */)
> +                     break;
> +             msleep(1);
> +     }
> +     pcicore_write32(pc, mdio_control, 0);
> +}
>
> ...
>
> +
> +static void ssb_buses_lock(void)
> +{
> +     if (!ssb_is_early_boot)
> +             mutex_lock(&buses_mutex);
> +}
> +
> +static void ssb_buses_unlock(void)
> +{
> +     if (!ssb_is_early_boot)
> +             mutex_unlock(&buses_mutex);
> +}

Some comments are neeeded here to explain why we're jumping through this
hoop.  It's normally OK to take a mutex early in boot, so one wonders
what's happening.

> +EXPORT_SYMBOL(ssb_clockspeed);

Please check that all newly-added exports really need to be exported (I'm
sure they do, but..)

> +static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
> +                     int timeout, int set)
> +{
> +     int i;
> +     u32 val;
> +
> +     for (i = 0; i < timeout; i++) {
> +             val = ssb_read32(dev, reg);
> +             if (set) {
> +                     if (val & bitmask)
> +                             return 0;
> +             } else {
> +                     if (!(val & bitmask))
> +                             return 0;
> +             }
> +             udelay(10);
> +     }
> +     printk(KERN_ERR PFX "Timeout waiting for bitmask %08X on "
> +                         "register %04X to %s.\n",
> +            bitmask, reg, (set ? "set" : "clear"));
> +
> +     return -ETIMEDOUT;
> +}

So `timeout' is in units of ten-microseconds.  Unusual.

> +void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
> +{
> +     u32 reject;
> +
> +     if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
> +             return;
> +
> +     reject = ssb_tmslow_reject_bitmask(dev);
> +     ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
> +     ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
> +     ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
> +     ssb_write32(dev, SSB_TMSLOW,
> +                 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
> +                 reject | SSB_TMSLOW_RESET |
> +                 core_specific_flags);
> +     /* flush */
> +     ssb_read32(dev, SSB_TMSLOW);
> +     udelay(1);
> +
> +     ssb_write32(dev, SSB_TMSLOW,
> +                 reject | SSB_TMSLOW_RESET |
> +                 core_specific_flags);
> +     /* flush */
> +     ssb_read32(dev, SSB_TMSLOW);
> +     udelay(1);

mystery udelay.

> +}
> +EXPORT_SYMBOL(ssb_device_disable);
>
> ...
>
> +const struct ssb_bus_ops ssb_pci_ops = {
> +     .read16         = ssb_pci_read16,
> +     .read32         = ssb_pci_read32,
> +     .write16        = ssb_pci_write16,
> +     .write32        = ssb_pci_write32,
> +};

static?

> +static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
> +                                    struct device_attribute *attr,
> +                                    char *buf)
> +{
> +     struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
> +     struct ssb_bus *bus;
> +     u16 *sprom;
> +     int err = -ENODEV;
> +     ssize_t count = 0;
> +
> +     bus = ssb_pci_dev_to_bus(pdev);
> +     if (!bus)
> +             goto out;
> +     err = -ENOMEM;
> +     sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
> +     if (!sprom)
> +             goto out;
> +
> +     err = -ERESTARTSYS;
> +     if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
> +             goto out_kfree;
> +     sprom_do_read(bus, sprom);
> +     mutex_unlock(&bus->pci_sprom_mutex);
> +
> +     count = sprom2hex(sprom, buf, PAGE_SIZE);
> +     err = 0;
> +
> +out_kfree:
> +     kfree(sprom);
> +out:
> +     return err ? err : count;
> +}

The mutex_lock_interruptible() looks fishy.  Some commented explanation of
what it's doing would be good here.  It's quite unobvious to this reader. 
Cheesy deadlock avoidance?  Hope not.

> +
> +/* These are the main device register access functions.
> + * do_select_core is inline to have the likely hotpath inline.
> + * All unlikely codepaths are out-of-line. */
> +static inline int do_select_core(struct ssb_bus *bus,
> +                              struct ssb_device *dev,
> +                              u16 *offset)
> +{
> +     int err;
> +     u8 need_seg = (*offset >= 0x800) ? 1 : 0;
> +
> +     if (unlikely(dev != bus->mapped_device)) {
> +             err = ssb_pcmcia_switch_core(bus, dev);
> +             if (unlikely(err))
> +                     return err;
> +     }
> +     if (unlikely(need_seg != bus->mapped_pcmcia_seg)) {
> +             err = ssb_pcmcia_switch_segment(bus, need_seg);
> +             if (unlikely(err))
> +                     return err;
> +     }
> +     if (need_seg == 1)
> +             *offset -= 0x800;
> +
> +     return 0;
> +}

Looks too large for inlining.

> +const struct ssb_bus_ops ssb_pcmcia_ops = {
> +     .read16         = ssb_pcmcia_read16,
> +     .read32         = ssb_pcmcia_read32,
> +     .write16        = ssb_pcmcia_write16,
> +     .write32        = ssb_pcmcia_write32,
> +};

static?


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to