From 4dbedf43d26276f6d7c8c3146d0a5b2f0309d968 Mon Sep 17 00:00:00 2001 From: Nathan Williams Date: Wed, 25 Mar 2009 20:27:37 +1100 Subject: [PATCH 1/4] solos: support new FPGA RAM layout Buffer sizes have been changed to 2048 bytes. Flash upgrades use a dedicated RAM block. Add support for daughterboard. Signed-off-by: Nathan Williams Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 71 +++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index bc3079d17876..bfef8d255811 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -59,21 +59,29 @@ #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define DATA_RAM_SIZE 32768 -#define BUF_SIZE 4096 +#define BUF_SIZE 2048 +#define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ #define FPGA_PAGE 528 /* FPGA flash page size*/ #define SOLOS_PAGE 512 /* Solos flash page size*/ #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ -#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) -#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) +#define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) +#define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) +#define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2) #define RX_DMA_SIZE 2048 +#define FPGA_VERSION(a,b) (((a) << 8) + (b)) +#define LEGACY_BUFFERS 2 +#define DMA_SUPPORTED 4 + static int reset = 0; static int atmdebug = 0; static int firmware_upgrade = 0; static int fpga_upgrade = 0; +static int db_firmware_upgrade = 0; +static int db_fpga_upgrade = 0; struct pkt_hdr { __le16 size; @@ -116,6 +124,8 @@ struct solos_card { wait_queue_head_t param_wq; wait_queue_head_t fw_wq; int using_dma; + int fpga_version; + int buffer_size; }; @@ -136,10 +146,14 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); +MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade"); +MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade"); module_param(reset, int, 0444); module_param(atmdebug, int, 0644); module_param(firmware_upgrade, int, 0444); module_param(fpga_upgrade, int, 0444); +module_param(db_firmware_upgrade, int, 0444); +module_param(db_fpga_upgrade, int, 0444); static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, struct atm_vcc *vcc); @@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip) if (chip == 0) { fw_name = "solos-FPGA.bin"; blocksize = FPGA_BLOCK; - } else { + } + + if (chip == 1) { fw_name = "solos-Firmware.bin"; blocksize = SOLOS_BLOCK; } + + if (chip == 2){ + if (card->fpga_version > LEGACY_BUFFERS){ + fw_name = "solos-db-FPGA.bin"; + blocksize = FPGA_BLOCK; + } else { + dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n"); + return -EPERM; + } + } + + if (chip == 3){ + if (card->fpga_version > LEGACY_BUFFERS){ + fw_name = "solos-Firmware.bin"; + blocksize = SOLOS_BLOCK; + } else { + dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n"); + return -EPERM; + } + } if (request_firmware(&fw, fw_name, &card->dev->dev)) return -ENOENT; @@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip) data32 = ioread32(card->config_regs + FPGA_MODE); /* Set mode to Chip Erase */ - dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n", - chip?"Solos":"FPGA"); + if(chip == 0 || chip == 2) + dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n"); + if(chip == 1 || chip == 3) + dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n"); iowrite32((chip * 2), card->config_regs + FLASH_MODE); @@ -557,7 +595,10 @@ static int flash_upgrade(struct solos_card *card, int chip) /* Copy block to buffer, swapping each 16 bits */ for(i = 0; i < blocksize; i += 4) { uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); - iowrite32(word, RX_BUF(card, 3) + i); + if(card->fpga_version > LEGACY_BUFFERS) + iowrite32(word, FLASH_BUF + i); + else + iowrite32(word, RX_BUF(card, 3) + i); } /* Specify block number and then trigger flash write */ @@ -1094,12 +1135,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) fpga_ver = (data32 & 0x0000FFFF); major_ver = ((data32 & 0xFF000000) >> 24); minor_ver = ((data32 & 0x00FF0000) >> 16); + card->fpga_version = FPGA_VERSION(major_ver,minor_ver); + if (card->fpga_version > LEGACY_BUFFERS) + card->buffer_size = BUF_SIZE; + else + card->buffer_size = OLD_BUF_SIZE; dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", major_ver, minor_ver, fpga_ver); - if (0 && fpga_ver > 27) + if (card->fpga_version >= DMA_SUPPORTED){ card->using_dma = 1; - else { + } else { + card->using_dma = 0; /* Set RX empty flag for all ports */ iowrite32(0xF0, card->config_regs + FLAGS_ADDR); } @@ -1131,6 +1178,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) if (firmware_upgrade) flash_upgrade(card, 1); + if (db_fpga_upgrade) + flash_upgrade(card, 2); + + if (db_firmware_upgrade) + flash_upgrade(card, 3); + err = atm_init(card); if (err) goto out_free_irq; From 78f857f265241dfa6f343d75b45e8b30935f71df Mon Sep 17 00:00:00 2001 From: Nathan Williams Date: Wed, 25 Mar 2009 20:33:42 +1100 Subject: [PATCH 2/4] solos: Check for rogue received packets Sometimes there can be received packets with the size field set to 0xFFFF. This seems to only occur after an FPGA or firmware upgrade. This patch discards packets with an invalid size. Signed-off-by: Nathan Williams Signed-off-by: David Woodhouse --- drivers/atm/solos-pci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index bfef8d255811..6c828347c9cc 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -671,6 +671,10 @@ void solos_bh(unsigned long card_arg) memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); size = le16_to_cpu(header->size); + if (size > (card->buffer_size - sizeof(*header))){ + dev_warn(&card->dev->dev, "Invalid buffer size\n"); + continue; + } skb = alloc_skb(size + 1, GFP_ATOMIC); if (!skb) { From a3434660e5b47ab90387b017e311437bb3a88083 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 30 Apr 2009 15:38:01 +0100 Subject: [PATCH 3/4] solos: Add some margin-related parameters Signed-off-by: David Woodhouse --- drivers/atm/solos-attrlist.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c index efa2808dd94d..946726399398 100644 --- a/drivers/atm/solos-attrlist.c +++ b/drivers/atm/solos-attrlist.c @@ -62,6 +62,13 @@ SOLOS_ATTR_RW(Defaults) SOLOS_ATTR_RW(LineMode) SOLOS_ATTR_RW(Profile) SOLOS_ATTR_RW(DetectNoise) +SOLOS_ATTR_RW(BisAForceSNRMarginDn) +SOLOS_ATTR_RW(BisMForceSNRMarginDn) +SOLOS_ATTR_RW(BisAMaxMargin) +SOLOS_ATTR_RW(BisMMaxMargin) +SOLOS_ATTR_RW(AnnexAForceSNRMarginDn) +SOLOS_ATTR_RW(AnnexAMaxMargin) +SOLOS_ATTR_RW(AnnexMMaxMargin) SOLOS_ATTR_RO(SupportedAnnexes) SOLOS_ATTR_RO(Status) SOLOS_ATTR_RO(TotalStart) From 69a9ceab83928e743fafbba5b98bd09aed7c0e0d Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Thu, 7 May 2009 19:43:42 +0100 Subject: [PATCH 4/4] solos: Show Interleaving details for ADSL2 and 2+ InterleaveRDn and InterleaveRUp only apply to G.dmt. The equivalents for ADSL2 and 2+ are BisRDn and BisRUp. In addition, the INPdown and INPup statuses are useful when trying to track down instability on a line. Signed-off-by: Simon Farnsworth Signed-off-by: David Woodhouse --- drivers/atm/solos-attrlist.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c index 946726399398..1a9332e4efe0 100644 --- a/drivers/atm/solos-attrlist.c +++ b/drivers/atm/solos-attrlist.c @@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp) SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) SOLOS_ATTR_RO(InterleaveRDn) SOLOS_ATTR_RO(InterleaveRUp) +SOLOS_ATTR_RO(BisRDn) +SOLOS_ATTR_RO(BisRUp) +SOLOS_ATTR_RO(INPdown) +SOLOS_ATTR_RO(INPup) SOLOS_ATTR_RO(ShowtimeStart) SOLOS_ATTR_RO(ATURVendor) SOLOS_ATTR_RO(ATUCCountry)