On Saturday 09 November 2013, Loc Ho wrote:
> +
> +#undef XGENE_DBG_CSR         /* Enable CSR read/write dumping */
> +#ifdef XGENE_DBG_CSR
> +#define XGENE_CSRDBG(fmt, args...)   \
> +     printk(KERN_INFO "XGENESATA: " fmt "\n", ## args);
> +#else
> +#define XGENE_CSRDBG(fmt, args...)
> +#endif

Please kill those private debug macros and use the generic interfaces.

> +void xgene_ahci_delayus(unsigned long us)
> +{
> +     udelay(us);
> +}
> +
> +void xgene_ahci_delayms(unsigned long us)
> +{
> +     mdelay(us);
> +}

Same for these pointless wrappers. Also every use of mdelay and ideally also 
udelay
needs a good explanation about why the hardware is so broken to require it or
why you cannot use msleep().

> +static int xgene_ahci_get_irq(struct platform_device *pdev, int index)
> +{
> +     if (efi_enabled(EFI_BOOT))
> +             return platform_get_irq(pdev, index);
> +     return irq_of_parse_and_map(pdev->dev.of_node, index);
> +}
> +
> +static int xgene_ahci_get_resource(struct platform_device *pdev, int index,
> +                                struct resource *res)
> +{
> +     struct resource *regs;
> +     if (efi_enabled(EFI_BOOT)) {
> +             regs = platform_get_resource(pdev, IORESOURCE_MEM, index);
> +             if (regs == NULL)
> +                     return -ENODEV;
> +             *res = *regs;
> +             return 0;
> +     }
> +     return of_address_to_resource(pdev->dev.of_node, index, res);
> +}

These wrappers look wrong. Why can't you always use 
platform_get_irq/platform_get_resource?
What does the use of the of_* interfaces have to do with EFI?

> +static int xgene_ahci_get_u32_param(struct platform_device *pdev,
> +                                 const char *of_name, char *acpi_name,
> +                                 u32 *param)
> +{
> +#ifdef CONFIG_ACPI
> +     if (efi_enabled(EFI_BOOT)) {
> +             unsigned long long value;
> +             acpi_status status;
> +             if (acpi_name == NULL)
> +                     return -ENODEV;
> +             status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev),
> +                                            acpi_name, NULL, &value);
> +             if (ACPI_FAILURE(status))
> +                     return -ENODEV;
> +             *param = value;
> +             return 0;
> +     }
> +#endif
> +     if (of_name == NULL)
> +             return -ENODEV;
> +     return of_property_read_u32(pdev->dev.of_node, of_name, param);
> +}

This is worse. A device driver is *not* the place to put abstractions for
the bindings, those belong into common code.
Also it seems you are trying to do register-level programming based on
attributes you pull out of the respective firmware interfaces.

While there has been some progress regarding getting a common direction
for embedded x86 machines using ACPI, you should not assume that the same
makes sense for ARM systems.

* In case of the Open Firmware DT, the model is that we use per-subsystem
  bindings to describe the hardware in an abstract way, e.g. using the
  PHY controller, reset controller, clock controller, ... APIs. This is
  how we can handle complex SoC-type systems.

* In case of a server-class ACPI based machine, the model is that those
  details are handled by the firmware and you don't need to bother the
  device driver with them.

> +     rc = xgene_ahci_get_str_param(pdev, "clock-names", "CLNM", res_name,
> +                                   sizeof(res_name));
> +     if (rc) {
> +             dev_err(&pdev->dev, "no clock name resource\n");
> +             goto error;
> +     }

As mentioned in the other mail, the driver must not read the "clock-names"
property but have a hardcoded name for the clock (or use NULL for simplicity).

> +     if (strcmp(res_name, "eth01clk") == 0)
> +             hpriv->cid = 0;
> +     else if (strcmp(res_name, "eth23clk") == 0)
> +             hpriv->cid = 1;
> +     else
> +             hpriv->cid = 2;
> +
> +     if (hpriv->cid == 2) {
> +             rc = xgene_ahci_get_resource(pdev, 2, &res);
> +             if (rc != 0) {
> +                     dev_err(&pdev->dev, "no SATA/PCIE resource address\n");
> +                     goto error;
> +             }
> +             hpriv->pcie_base = devm_ioremap(&pdev->dev, res.start,
> +                                             resource_size(&res));
> +             if (!hpriv->pcie_base) {
> +                     dev_err(&pdev->dev, "can't map SATA/PCIe resource\n");
> +                     rc = -ENOMEM;
> +                     goto error;
> +             }
> +     }

This seems to incorrectly rely on side-effects of which particular clock
gets used. What are you trying to do here?

> +     /* Custom Serdes override paraemter */
> +     rc = xgene_ahci_get_u32_param(pdev, "gen-sel", "GENS", &gen_sel);
> +     if (rc != 0)
> +             gen_sel = 3;    /* Default to Gen3 */
> +     rc = xgene_ahci_get_u32_param(pdev, "serdes-diff-clk", "SDCL",
> +                                   &serdes_diff_clk);
> +     if (rc != 0)
> +             serdes_diff_clk = SATA_CLK_EXT_DIFF; /* Default to external */
> +     rc = xgene_ahci_get_u32_param(pdev, "EQA1", "EQA1",
> +                                   &hpriv->ctrl_eq_A1);
> +     if (rc != 0)
> +             hpriv->ctrl_eq_A1 = CTLE_EQ;
> +     rc = xgene_ahci_get_u32_param(pdev, "EQ", "EQ00", &hpriv->ctrl_eq);
> +     if (rc != 0)
> +             hpriv->ctrl_eq = CTLE_EQ_A2;
> +     dev_dbg(&pdev->dev, "SATA%d ctrl_eq %u %u\n", hpriv->cid,
> +             hpriv->ctrl_eq_A1, hpriv->ctrl_eq);
> +     rc = xgene_ahci_get_u32_param(pdev, "GENAVG", "GAVG",
> +                                   &hpriv->use_gen_avg);
> +     if (rc != 0)
> +             hpriv->use_gen_avg = xgene_ahci_is_A1() ? 0 : 1;
> +     dev_dbg(&pdev->dev, "SATA%d use avg %u\n", hpriv->cid,
> +             hpriv->use_gen_avg);
> +     rc = xgene_ahci_get_u32_param(pdev, "LBA1", "LBA1",
> +                                   &hpriv->loopback_buf_en_A1);
> +     if (rc != 0)
> +             hpriv->loopback_buf_en_A1 = 1;
> +     rc = xgene_ahci_get_u32_param(pdev, "LB", "LB00",
> +                                   &hpriv->loopback_buf_en);
> +     if (rc != 0)
> +             hpriv->loopback_buf_en = 0;
> +     dev_dbg(&pdev->dev, "SATA%d loopback_buf_en %u %u\n", hpriv->cid,
> +             hpriv->loopback_buf_en_A1, hpriv->loopback_buf_en);
> +     rc = xgene_ahci_get_u32_param(pdev, "LCA1", "LCA1",
> +                                   &hpriv->loopback_ena_ctle_A1);
> +     if (rc != 0)
> +             hpriv->loopback_ena_ctle_A1 = 1;
> +     rc = xgene_ahci_get_u32_param(pdev, "LC", "LC00",
> +                                   &hpriv->loopback_ena_ctle);
> +     if (rc != 0)
> +             hpriv->loopback_ena_ctle = 0;
> +     dev_dbg(&pdev->dev, "SATA%d loopback_ena_ctle %u %u\n", hpriv->cid,
> +             hpriv->loopback_ena_ctle_A1, hpriv->loopback_ena_ctle);
> +     rc = xgene_ahci_get_u32_param(pdev, "CDRA1", "CDR1",
> +                                   &hpriv->spd_sel_cdr_A1);
> +     if (rc != 0)
> +             hpriv->spd_sel_cdr_A1 = SPD_SEL;
> +     rc = xgene_ahci_get_u32_param(pdev, "CDR", "CDR0",
> +                                   &hpriv->spd_sel_cdr);
> +     if (rc != 0)
> +             hpriv->spd_sel_cdr = SPD_SEL;
> +     dev_dbg(&pdev->dev, "SATA%d spd_sel_cdr %u %u\n", hpriv->cid,
> +             hpriv->spd_sel_cdr_A1, hpriv->spd_sel_cdr);
> +     rc = xgene_ahci_get_u32_param(pdev, "PQA1", "PQA1", &hpriv->pq_A1);
> +     if (rc != 0)
> +             hpriv->pq_A1 = PQ_REG;
> +     rc = xgene_ahci_get_u32_param(pdev, "PQ", "PQ00", &hpriv->pq);

All this this crap can probably just go away if you have a proper PHY driver
(in case of DT) or handle it in the firmware (in case of a server).

> +     if (rc != 0)
> +             hpriv->pq = PQ_REG_A2;
> +     hpriv->pq_sign = 0x1;
> +     dev_dbg(&pdev->dev, "SATA%d pq %u %u %d\n", hpriv->cid, hpriv->pq_A1,
> +             hpriv->pq, hpriv->pq_sign);
> +     rc = xgene_ahci_get_u32_param(pdev, "coherent", "COHT",
> +                                   &hpriv->coherent);

Coherency should be managed by the DMA-mapping API, don't introduce custom
properties for this.

> +     /* Setup DMA mask */
> +     pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
> +     pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);

Drivers are not allowed to touch these fields directly, you have to use
dma_set_mask/dma_set_coherent_mask so the architecture code can check
that the bus is actually 64-bit capable.

> +static int xgene_ahci_remove(struct platform_device *pdev)
> +{
> +     struct ata_host *host = dev_get_drvdata(&pdev->dev);
> +     struct xgene_ahci_context *hpriv = host->private_data;
> +
> +     dev_dbg(&pdev->dev, "SATA%d remove\n", hpriv->cid);
> +     devm_kfree(&pdev->dev, hpriv);
> +     return 0;
> +}

The devm_kfree seems pointless here.

        Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to