@@ -48,74 +48,19 @@
static int hss_set_clock(int port, unsigned int clock_type)
{
- /*int ctrl_int = port ? CONTROL_HSS1_CLK_INT : CONTROL_HSS0_CLK_INT;
-
- switch (clock_type) {
- case CLOCK_DEFAULT:
- case CLOCK_EXT:
- set_control(ctrl_int, 0);
- output_control();
- return CLOCK_EXT;
-
- case CLOCK_INT:
- set_control(ctrl_int, 1);
- output_control();
- return CLOCK_INT;
-
- default:
- return -EINVAL;
- }*/
-}
-
-static irqreturn_t hss_dcd_irq(int irq, void *pdev)
-{
- /*int i, port = (irq == gpio_irq(GPIO_HSS1_DCD_N));
- gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i);
- set_carrier_cb_tab[port](pdev, !i);*/
- return IRQ_HANDLED;
+ return clock_type;
}
-
static int hss_open(int port, void *pdev,
void (*set_carrier_cb)(void *pdev, int carrier))
{
- /*
- int i, irq;
-
- if (!port)
- irq = gpio_irq(GPIO_HSS0_DCD_N);
- else
- irq = gpio_irq(GPIO_HSS1_DCD_N);
-
- gpio_line_get(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N, &i);
- set_carrier_cb(pdev, !i);
-
- set_carrier_cb_tab[!!port] = set_carrier_cb;
-
- if ((i = request_irq(irq, hss_dcd_irq, 0, "IXP4xx HSS", pdev)) != 0) {
- printk(KERN_ERR "ixp4xx_hss: failed to request IRQ%i\n", irq);
- return -EIO;
- }
-
- set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 0);
- output_control();
- gpio_line_set(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 0);
- */
return 0;
}
static void hss_close(int port, void *pdev)
{
- //free_irq(port ? gpio_irq(GPIO_HSS1_DCD_N) : gpio_irq(GPIO_HSS0_DCD_N),
- // pdev);
- //set_carrier_cb_tab[!!port] = NULL; /* catch bugs */
-
- //set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 1);
- //output_control();
- //gpio_line_set(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 1);
}
-
static struct flash_platform_data ixdp425_flash_data = {
.map_name = "cfi_probe",
.width = 2,@@ -321,12 +266,12 @@
static struct eth_plat_info ixdp425_plat_eth[] = {
{
.phy = 0,
- .rxq = 3,
- .txreadyq = 20,
+ .rxq = 10,
+ .txreadyq = 40,
}, {
.phy = 1,
- .rxq = 4,
- .txreadyq = 21,
+ .rxq = 11,
+ .txreadyq = 41,
}
};
@@ -349,12 +294,58 @@
.set_clock = hss_set_clock,
.open = hss_open,
.close = hss_close,
- .txreadyq = 2,
+ .txreadyq = 32,
+ .hss = 0,
+ .hdlc = 0,
}, {
.set_clock = hss_set_clock,
.open = hss_open,
.close = hss_close,
- .txreadyq = 19,
+ .txreadyq = 36,
+ .hss = 1,
+ .hdlc = 0,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 33,
+ .hss = 0,
+ .hdlc = 1,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 37,
+ .hss = 1,
+ .hdlc = 1,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 34,
+ .hss = 0,
+ .hdlc = 2,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 38,
+ .hss = 1,
+ .hdlc = 2,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 35,
+ .hss = 0,
+ .hdlc = 3,
+ }, {
+ .set_clock = hss_set_clock,
+ .open = hss_open,
+ .close = hss_close,
+ .txreadyq = 39,
+ .hss = 1,
+ .hdlc = 3,
}
};
@@ -367,6 +358,30 @@
.name = "ixp4xx_hss",
.id = 1,
.dev.platform_data = hss_plat + 1,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 2,
+ .dev.platform_data = hss_plat + 2,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 3,
+ .dev.platform_data = hss_plat + 3,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 4,
+ .dev.platform_data = hss_plat + 4,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 5,
+ .dev.platform_data = hss_plat + 5,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 6,
+ .dev.platform_data = hss_plat + 6,
+ }, {
+ .name = "ixp4xx_hss",
+ .id = 7,
+ .dev.platform_data = hss_plat + 7,
}
};
@@ -384,6 +399,12 @@
&ixdp425_spi,
&device_hss_tab[0],
&device_hss_tab[1],
+ &device_hss_tab[2],
+ &device_hss_tab[3],
+ &device_hss_tab[4],
+ &device_hss_tab[5],
+ &device_hss_tab[6],
+ &device_hss_tab[7],
};
/*static struct spi_board_info spi_board_info[] __initdata = { {@@ -95,75 +100,96 @@
#define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */
#define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */
#define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */
+#define PKT_EXTRA_FLAGS 0 /* orig 1 frmFlagStart */
-
+/* HSSTXPCR / HSSRXPCR */
/* hss_config, PCRs */
-/* Frame sync sampling, default = active low */
+/* Frame sync sampling, default = active low (FTYPE bits 30,31)*/
#define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000
#define PCR_FRM_SYNC_FALLINGEDGE 0x80000000
#define PCR_FRM_SYNC_RISINGEDGE 0xC0000000
/* Frame sync pin: input (default) or output generated off a given clk edge */
+/* (FENABLE bits 28, 29) */
#define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000
#define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000
/* Frame and data clock sampling on edge, default = falling */
+/* (FEDGE bit 27) */
#define PCR_FCLK_EDGE_RISING 0x08000000
+/* (DEDGE bit 26) */
#define PCR_DCLK_EDGE_RISING 0x04000000
/* Clock direction, default = input */
+/* (CLKDIR bit 25) */
#define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000
/* Generate/Receive frame pulses, default = enabled */
+/* (FRAME bit 24) */
#define PCR_FRM_PULSE_DISABLED 0x01000000
/* Data rate is full (default) or half the configured clk speed */
+/* (HALF bit 21) */
#define PCR_HALF_CLK_RATE 0x00200000
/* Invert data between NPE and HSS FIFOs? (default = no) */
+/* (DPOL bit 20) */
#define PCR_DATA_POLARITY_INVERT 0x00100000
/* TX/RX endianness, default = LSB */
+/* (BITEND bit 19) */
#define PCR_MSB_ENDIAN 0x00080000
/* Normal (default) / open drain mode (TX only) */
+/* (ODRAIN bin 18 TX) */
#define PCR_TX_PINS_OPEN_DRAIN 0x00040000
/* No framing bit transmitted and expected on RX? (default = framing bit) */
+/* (FBIT bit 17) */
#define PCR_SOF_NO_FBIT 0x00020000
/* Drive data pins? */
+/* (ENABLE bit 16 TX) */
#define PCR_TX_DATA_ENABLE 0x00010000
/* Voice 56k type: drive the data pins low (default), high, high Z */
+/* (56KTYPE bits 13, 14 (and 15?) TX) */
#define PCR_TX_V56K_HIGH 0x00002000
#define PCR_TX_V56K_HIGH_IMP 0x00004000
/* Unassigned type: drive the data pins low (default), high, high Z */
+/* (UTYPE bits 11, 12 TX) */
#define PCR_TX_UNASS_HIGH 0x00000800
#define PCR_TX_UNASS_HIGH_IMP 0x00001000
/* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */
+/* (FBTYPE bit 10 TX) */
#define PCR_TX_FB_HIGH_IMP 0x00000400
/* 56k data endiannes - which bit unused: high (default) or low */
+/* (56KEND bit 9 TX) */
#define PCR_TX_56KE_BIT_0_UNUSED 0x00000200
/* 56k data transmission type: 32/8 bit data (default) or 56K data */
+/* (56KSEL bit 8 TX) */
#define PCR_TX_56KS_56K_DATA 0x00000100
+/* HSSCCR */
/* hss_config, cCR */
/* Number of packetized clients, default = 1 */
+/* (HFIFO bits 26, 27) */
#define CCR_NPE_HFIFO_2_HDLC 0x04000000
#define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000
/* default = no loopback */
+/* (LBACK bit 25) */
#define CCR_LOOPBACK 0x02000000
/* HSS number, default = 0 (first) */
+/* (COND bit 24) */
#define CCR_SECOND_HSS 0x01000000
-
+/* HSSCLKCR */
/* hss_config, clkCR: main:10, num:10, denom:12 */
#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/
@@ -273,16 +299,28 @@
u8 log_channels[MAX_CHANNELS];
};
+struct hss_t
+{
+ unsigned int id;
+ u8 hdlc_open;
+ u32 slots[MAX_CHANNELS];
+ u32 mask[MAX_CHANNELS];
+ struct port *npe_port_tab[HDLC_COUNT];
+ struct napi_struct napi;
+};
+
struct port {
struct device *dev;
struct npe *npe;
struct net_device *netdev;
- struct napi_struct napi;
struct hss_plat_info *plat;
buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
struct desc *desc_tab; /* coherent */
u32 desc_tab_phys;
+ u32 pending_phys;
unsigned int id;
+ struct hss_t* hss;
+ unsigned int hdlc;
atomic_t chan_tx_irq_number, chan_rx_irq_number;
wait_queue_head_t chan_tx_waitq, chan_rx_waitq;
u8 hdlc_cfg;@@ -290,6 +328,7 @@
/* the following fields must be protected by npe_lock */
enum mode mode;
unsigned int clock_type, clock_rate, loopback;
+ unsigned int frame_sync_type;
unsigned int frame_size, frame_sync_offset;
struct chan_device *chan_devices[MAX_CHAN_DEVICES];
@@ -380,18 +419,73 @@
static spinlock_t npe_lock;
static DEFINE_MUTEX(firmware_mutex);
+static struct hss_t hss[HSS_COUNT] = {
+ {0, 0},
+ {1, 0},
+};
+
static const struct {
int tx, txdone, rx, rxfree, chan;
-}queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+}queue_ids[8] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
HSS0_PKT_RXFREE0_QUEUE, HSS0_CHL_RXTRIG_QUEUE},
+ {HSS0_PKT_TX1_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+ HSS0_PKT_RXFREE1_QUEUE, HSS0_CHL_RXTRIG_QUEUE},
+ {HSS0_PKT_TX2_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+ HSS0_PKT_RXFREE2_QUEUE, HSS0_CHL_RXTRIG_QUEUE},
+ {HSS0_PKT_TX3_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+ HSS0_PKT_RXFREE3_QUEUE, HSS0_CHL_RXTRIG_QUEUE},
{HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
HSS1_PKT_RXFREE0_QUEUE, HSS1_CHL_RXTRIG_QUEUE},
+ {HSS1_PKT_TX1_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
+ HSS1_PKT_RXFREE1_QUEUE, HSS1_CHL_RXTRIG_QUEUE},
+ {HSS1_PKT_TX2_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
+ HSS1_PKT_RXFREE2_QUEUE, HSS1_CHL_RXTRIG_QUEUE},
+ {HSS1_PKT_TX3_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
+ HSS1_PKT_RXFREE3_QUEUE, HSS1_CHL_RXTRIG_QUEUE},
};
/*****************************************************************************
* utility functions
****************************************************************************/
+static u32 get_clock_config(u32 clock_rate) {
+ if (cpu_is_ixp42x()) {
+ switch (clock_rate) {
+ case 512000:
+ return CLK46X_SPEED_512KHZ;
+ case 1536000:
+ return CLK46X_SPEED_1536KHZ;
+ case 1544000:
+ return CLK46X_SPEED_1544KHZ;
+ case 2048000:
+ return CLK46X_SPEED_2048KHZ;
+ case 4096000:
+ return CLK46X_SPEED_4096KHZ;
+ case 8192000:
+ return CLK46X_SPEED_8192KHZ;
+ default:
+ return CLK46X_SPEED_2048KHZ;
+ }
+ } else {
+ switch (clock_rate) {
+ case 512000:
+ return CLK42X_SPEED_512KHZ;
+ case 1536000:
+ return CLK42X_SPEED_1536KHZ;
+ case 1544000:
+ return CLK42X_SPEED_1544KHZ;
+ case 2048000:
+ return CLK42X_SPEED_2048KHZ;
+ case 4096000:
+ return CLK42X_SPEED_4096KHZ;
+ case 8192000:
+ return CLK42X_SPEED_8192KHZ;
+ default:
+ return CLK42X_SPEED_2048KHZ;
+ }
+ }
+}
+
static inline struct port* dev_to_port(struct net_device *dev)
{
return dev_to_hdlc(dev)->priv;@@ -521,18 +615,18 @@
{
struct msg msg;
int chan_count = 0, log_chan = 0, i, ch;
- u32 lut[MAX_CHANNELS / 4];
- memset(lut, 0, sizeof(lut));
for (i = 0; i < MAX_CHAN_DEVICES; i++)
if (port->chan_devices[i])
port->chan_devices[i]->chan_count = 0;
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
for (ch = 0; ch < MAX_CHANNELS; ch++) {
+ if (ch >= MAX_CHANNELS)
+ break;
struct chan_device *chdev = NULL;
unsigned int entry;
@@ -541,8 +635,15 @@
if (port->mode == MODE_G704 && ch == 0)
entry = TDMMAP_VOICE64K; /* PCM-31 pattern */
- else if (port->mode == MODE_HDLC ||
- port->channels[ch] == CHANNEL_HDLC)
+ else if (port->mode == MODE_HDLC) {
+ if (port->hss->slots[ch] && port->hss->slots[ch]) {
+ entry = TDMMAP_HDLC;
+ }
+ else {
+ entry = TDMMAP_UNASSIGNED;
+ }
+ }
+ else if (port->channels[ch] == CHANNEL_HDLC)
entry = TDMMAP_HDLC;
else if (chdev && chdev->open_count) {
entry = TDMMAP_VOICE64K;@@ -571,7 +672,7 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_NUM_CHANS_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data8a = chan_count;
hss_npe_send(port, &msg, "CHAN_NUM_CHANS_WRITE");
@@ -598,38 +699,59 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.index = HSS_CONFIG_TX_PCR;
- msg.data32 = PCR_FRM_SYNC_OUTPUT_RISING | PCR_MSB_ENDIAN |
- PCR_TX_DATA_ENABLE;
+ msg.data32 = PCR_TX_DATA_ENABLE;
+ msg.data32 |= PCR_MSB_ENDIAN;
+ //msg.data32 |= PCR_FRM_SYNC_ACTIVE_HIGH;
+ if (port->frame_sync_type == FRAME_SYNC_INT_RISE)
+ msg.data32 |= PCR_FRM_SYNC_OUTPUT_RISING;
+ else if (port->frame_sync_type == FRAME_SYNC_INT_FALL)
+ msg.data32 |= PCR_FRM_SYNC_OUTPUT_FALLING;
if (port->frame_size % 8 == 0)
msg.data32 |= PCR_SOF_NO_FBIT;
if (port->clock_type == CLOCK_INT)
msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT;
+ //msg.data32 |= PCR_DCLK_EDGE_RISING;
hss_npe_send(port, &msg, "HSS_SET_TX_PCR");
msg.index = HSS_CONFIG_RX_PCR;
- msg.data32 ^= PCR_TX_DATA_ENABLE | PCR_DCLK_EDGE_RISING;
+ msg.data32 = 0;
+ msg.data32 |= PCR_MSB_ENDIAN;
+ //msg.data32 ^= PCR_FRM_SYNC_ACTIVE_HIGH;
+ if (port->frame_sync_type == FRAME_SYNC_INT_RISE)
+ msg.data32 |= PCR_FRM_SYNC_OUTPUT_RISING;
+ else if (port->frame_sync_type == FRAME_SYNC_INT_FALL)
+ msg.data32 |= PCR_FRM_SYNC_OUTPUT_FALLING;
+ if (port->frame_size % 8 == 0)
+ msg.data32 |= PCR_SOF_NO_FBIT;
+ if (port->clock_type == CLOCK_INT)
+ msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT;
+ msg.data32 |= PCR_DCLK_EDGE_RISING;
hss_npe_send(port, &msg, "HSS_SET_RX_PCR");
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.index = HSS_CONFIG_CORE_CR;
msg.data32 = (port->loopback ? CCR_LOOPBACK : 0) |
- (port->id ? CCR_SECOND_HSS : 0);
+ (port->hss->id ? CCR_SECOND_HSS : 0);
+ if ((256 < port->frame_size) && (port->frame_size <= 512))
+ msg.data32 |= CCR_NPE_HFIFO_2_HDLC;
+ else if (port->frame_size > 512)
+ msg.data32 |= CCR_NPE_HFIFO_3_OR_4HDLC;
hss_npe_send(port, &msg, "HSS_SET_CORE_CR");
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.index = HSS_CONFIG_CLOCK_CR;
- msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */;
+ msg.data32 = get_clock_config(port->clock_rate);
hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR");
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.index = HSS_CONFIG_TX_FCR;
msg.data16a = TX_FRAME_SYNC_OFFSET;
msg.data16b = port->frame_size - 1;
@@ -637,7 +759,7 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.index = HSS_CONFIG_RX_FCR;
msg.data16a = port->frame_sync_offset;
msg.data16b = port->frame_size - 1;
@@ -647,7 +769,7 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_CONFIG_LOAD;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
hss_npe_send(port, &msg, "HSS_LOAD_CONFIG");
if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
@@ -668,7 +790,8 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PKT_PIPE_HDLC_CFG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
+ msg.index = port->hdlc;
msg.data8a = port->hdlc_cfg; /* rx_cfg */
msg.data8b = port->hdlc_cfg | (PKT_EXTRA_FLAGS << 3); /* tx_cfg */
hss_npe_send(port, &msg, "HSS_SET_HDLC_CFG");
@@ -680,7 +803,7 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PORT_ERROR_READ;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
hss_npe_send(port, &msg, "PORT_ERROR_READ");
if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",@@ -700,19 +823,19 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_RX_BUF_ADDR_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data32 = port->chan_rx_buf_phys;
hss_npe_send(port, &msg, "CHAN_RX_BUF_ADDR_WRITE");
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_TX_BUF_ADDR_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data32 = chan_tx_lists_phys(port);
hss_npe_send(port, &msg, "CHAN_TX_BUF_ADDR_WRITE");
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_FLOW_ENABLE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
hss_npe_send(port, &msg, "CHAN_FLOW_ENABLE");
port->chan_started = 1;
}
@@ -726,7 +849,7 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_FLOW_DISABLE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
hss_npe_send(port, &msg, "CHAN_FLOW_DISABLE");
hss_get_status(port); /* make sure it's halted */
@@ -739,7 +862,8 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PKT_PIPE_FLOW_ENABLE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
+ msg.index = port->hdlc;
msg.data32 = 0;
hss_npe_send(port, &msg, "HSS_ENABLE_PKT_PIPE");
}
@@ -750,7 +874,8 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = PKT_PIPE_FLOW_DISABLE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
+ msg.index = port->hdlc;
hss_npe_send(port, &msg, "HSS_DISABLE_PKT_PIPE");
hss_get_status(port); /* make sure it's halted */
}
@@ -774,32 +899,37 @@
/* HDLC mode configuration */
memset(&msg, 0, sizeof(msg));
msg.cmd = PKT_NUM_PIPES_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
+ msg.index = 0;
msg.data8a = PKT_NUM_PIPES;
hss_npe_send(port, &msg, "HSS_SET_PKT_PIPES");
msg.cmd = PKT_PIPE_FIFO_SIZEW_WRITE;
+ msg.index = port->hdlc;
msg.data8a = PKT_PIPE_FIFO_SIZEW;
hss_npe_send(port, &msg, "HSS_SET_PKT_FIFO");
msg.cmd = PKT_PIPE_MODE_WRITE;
+ msg.index = port->hdlc;
msg.data8a = NPE_PKT_MODE_HDLC;
/* msg.data8b = inv_mask */
/* msg.data8c = or_mask */
hss_npe_send(port, &msg, "HSS_SET_PKT_MODE");
msg.cmd = PKT_PIPE_RX_SIZE_WRITE;
+ msg.index = port->hdlc;
msg.data16a = HDLC_MAX_MRU; /* including CRC */
hss_npe_send(port, &msg, "HSS_SET_PKT_RX_SIZE");
msg.cmd = PKT_PIPE_IDLE_PATTERN_WRITE;
+ msg.index = port->hdlc;
msg.data32 = 0x7F7F7F7F; /* ??? FIXME */
hss_npe_send(port, &msg, "HSS_SET_PKT_IDLE");
/* Channelized operation settings */
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_TX_BLK_CFG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data8b = (CHAN_TX_LIST_FRAMES & ~7) / 2;
msg.data8a = msg.data8b / 4;
msg.data8d = CHAN_TX_LIST_FRAMES - msg.data8b;
@@ -808,14 +938,14 @@
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_RX_BUF_CFG_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data8a = CHAN_RX_TRIGGER / 8;
msg.data8b = CHAN_RX_FRAMES;
hss_npe_send(port, &msg, "CHAN_RX_BUF_CFG_WRITE");
memset(&msg, 0, sizeof(msg));
msg.cmd = CHAN_TX_BUF_SIZE_WRITE;
- msg.hss_port = port->id;
+ msg.hss_port = port->hss->id;
msg.data8a = CHAN_TX_LISTS;
hss_npe_send(port, &msg, "CHAN_TX_BUF_SIZE_WRITE");
@@ -839,9 +969,9 @@
for (i = 0; i < len; i++) {
if (i >= DEBUG_PKT_BYTES)
break;
- printk(KERN_DEBUG "%s%02X", !(i % 4) ? " " : "", data[i]);
+ printk("%s%02X", !(i % 4) ? " " : "", data[i]);
}
- printk(KERN_DEBUG "\n");
+ printk("\n");
#endif
}
@@ -862,14 +992,26 @@
int queue;
char *name;
} names[] = {
- { HSS0_PKT_TX0_QUEUE, "TX#0 " },
+ { HSS0_PKT_TX0_QUEUE, "TX#0-0 " },
+ { HSS0_PKT_TX1_QUEUE, "TX#0-1 " },
+ { HSS0_PKT_TX2_QUEUE, "TX#0-2 " },
+ { HSS0_PKT_TX3_QUEUE, "TX#0-3 " },
{ HSS0_PKT_TXDONE_QUEUE, "TX-done#0 " },
{ HSS0_PKT_RX_QUEUE, "RX#0 " },
- { HSS0_PKT_RXFREE0_QUEUE, "RX-free#0 " },
- { HSS1_PKT_TX0_QUEUE, "TX#1 " },
+ { HSS0_PKT_RXFREE0_QUEUE, "RX-free#0-0 " },
+ { HSS0_PKT_RXFREE1_QUEUE, "RX-free#0-1 " },
+ { HSS0_PKT_RXFREE2_QUEUE, "RX-free#0-2 " },
+ { HSS0_PKT_RXFREE3_QUEUE, "RX-free#0-3 " },
+ { HSS1_PKT_TX0_QUEUE, "TX#1-0 " },
+ { HSS1_PKT_TX1_QUEUE, "TX#1-1 " },
+ { HSS1_PKT_TX2_QUEUE, "TX#1-2 " },
+ { HSS1_PKT_TX3_QUEUE, "TX#1-3 " },
{ HSS1_PKT_TXDONE_QUEUE, "TX-done#1 " },
{ HSS1_PKT_RX_QUEUE, "RX#1 " },
- { HSS1_PKT_RXFREE0_QUEUE, "RX-free#1 " },
+ { HSS1_PKT_RXFREE0_QUEUE, "RX-free#1-0 " },
+ { HSS1_PKT_RXFREE1_QUEUE, "RX-free#1-1 " },
+ { HSS1_PKT_RXFREE2_QUEUE, "RX-free#1-2 " },
+ { HSS1_PKT_RXFREE3_QUEUE, "RX-free#1-3 " },
};
int i;
@@ -890,16 +1032,12 @@
return phys;
}
-static inline int queue_get_desc(unsigned int queue, struct port *port,
- int is_tx)
+static inline int phys_to_ndesc(struct port *port, int is_tx, u32 phys)
{
- u32 phys, tab_phys, n_desc;
+ u32 tab_phys, n_desc;
struct desc *tab;
- if (!(phys = queue_get_entry(queue)))
- return -1;
-
- BUG_ON(phys & 0x1F);
+ //BUG_ON(phys & 0x1F);
tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0);
tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0);
n_desc = (phys - tab_phys) / sizeof(struct desc);@@ -909,12 +1047,23 @@
return n_desc;
}
-static inline void queue_put_desc(unsigned int queue, u32 phys,
- struct desc *desc)
+static inline int queue_get_desc(unsigned int queue, struct port *port,
+ int is_tx)
+{
+ u32 phys;
+
+ if (!(phys = queue_get_entry(queue)))
+ return -1;
+
+ return phys_to_ndesc(port, is_tx, phys);
+}
+
+static inline void queue_put_desc(unsigned int queue,
+ u32 phys, struct desc *desc)
{
debug_queue(queue, 0, phys);
debug_desc(phys, desc);
- BUG_ON(phys & 0x1F);
+ //BUG_ON(phys & 0x1F);
qmgr_put_entry(queue, phys);
BUG_ON(qmgr_stat_overflow(queue));
}@@ -950,60 +1099,79 @@
spin_unlock_irqrestore(&npe_lock, flags);
}
-static void hss_hdlc_rx_irq(void *pdev)
+static void hss_hdlc_rx_irq(void *pdev, int hssid)
{
- struct net_device *dev = pdev;
- struct port *port = dev_to_port(dev);
-
#if DEBUG_RX
- printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name);
+ printk(KERN_DEBUG "hss%d: hss_hdlc_rx_irq\n", hssid);
#endif
- qmgr_disable_irq(queue_ids[port->id].rx);
- netif_rx_schedule(dev, &port->napi);
+ qmgr_disable_irq(queue_ids[hssid * 4].rx);
+ napi_schedule(&hss[hssid].napi);
+}
+
+static void hss_hdlc_rx_irq0(void *pdev)
+{
+ hss_hdlc_rx_irq(pdev, 0);
+}
+
+static void hss_hdlc_rx_irq1(void *pdev)
+{
+ hss_hdlc_rx_irq(pdev, 1);
}
static int hss_hdlc_poll(struct napi_struct *napi, int budget)
{
- struct port *port = container_of(napi, struct port, napi);
- struct net_device *dev = port->netdev;
- unsigned int rxq = queue_ids[port->id].rx;
- unsigned int rxfreeq = queue_ids[port->id].rxfree;
- struct net_device_stats *stats = hdlc_stats(dev);
+ struct hss_t *hss = container_of(napi, struct hss_t, napi);
+ unsigned int rxq = queue_ids[hss->id * 4].rx;
int received = 0;
#if DEBUG_RX
- printk(KERN_DEBUG "%s: hss_hdlc_poll\n", dev->name);
+ printk(KERN_DEBUG "hss%d: hss_hdlc_poll\n", hss->id);
#endif
while (received < budget) {
struct sk_buff *skb;
struct desc *desc;
- int n;
+ int n = -1;
+ struct port *port = NULL;
+ struct net_device *dev = NULL;
+ unsigned int rxfreeq = -1;
+ struct net_device_stats *stats = NULL;
#ifdef __ARMEB__
struct sk_buff *temp;
u32 phys;
#endif
-
- if ((n = queue_get_desc(rxq, port, 0)) < 0) {
+ u32 rxphys = queue_get_entry(queue_ids[hss->id * 4].rx);
+ if (rxphys != 0) {
+ u32 npe_id = rxphys & 3;
+ BUG_ON(npe_id >= HDLC_COUNT);
+ port = hss->npe_port_tab[npe_id];
+ if (port != NULL) {
+ dev = port->netdev;
+ rxfreeq = queue_ids[port->hss->id * 4 + port->hdlc].rxfree;
+ stats = hdlc_stats(dev);
+ n = phys_to_ndesc(port, 0, rxphys);
+ }
+ }
+ if (n < 0) {
#if DEBUG_RX
- printk(KERN_DEBUG "%s: hss_hdlc_poll"
- " netif_rx_complete\n", dev->name);
+ printk(KERN_DEBUG "hss%d: hss_hdlc_poll"
+ " netif_rx_complete\n", hss->id);
#endif
- netif_rx_complete(dev, napi);
+ napi_complete(napi);
qmgr_enable_irq(rxq);
if (!qmgr_stat_empty(rxq) &&
- netif_rx_reschedule(dev, napi)) {
+ napi_reschedule(napi)) {
#if DEBUG_RX
- printk(KERN_DEBUG "%s: hss_hdlc_poll"
+ printk(KERN_DEBUG "hss%d: hss_hdlc_poll"
" netif_rx_reschedule succeeded\n",
- dev->name);
+ hss->id);
#endif
qmgr_disable_irq(rxq);
continue;
}
#if DEBUG_RX
- printk(KERN_DEBUG "%s: hss_hdlc_poll all done\n",
- dev->name);
+ printk(KERN_DEBUG "hss%d: hss_hdlc_poll all done\n",
+ hss->id);
#endif
return received; /* all work done */
}@@ -1100,38 +1268,52 @@
return received; /* not all work done */
}
-
-static void hss_hdlc_txdone_irq(void *pdev)
+static void hss_hdlc_txdone_irq(void *pdev, int hssid)
{
- struct net_device *dev = pdev;
- struct port *port = dev_to_port(dev);
- struct net_device_stats *stats = hdlc_stats(dev);
- int n_desc;
+ u32 phys;
#if DEBUG_TX
printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n");
#endif
- while ((n_desc = queue_get_desc(queue_ids[port->id].txdone,
- port, 1)) >= 0) {
+
+ while ((phys = queue_get_entry(queue_ids[hssid * 4].txdone)) != 0) {
+ u32 npe_id, n_desc;
+ struct port *port;
struct desc *desc;
int start;
- desc = tx_desc_ptr(port, n_desc);
+ npe_id = phys & 3;
- stats->tx_packets++;
- stats->tx_bytes += desc->pkt_len;
+ BUG_ON(npe_id >= HDLC_COUNT);
+ port = hss[hssid].npe_port_tab[npe_id];
+ BUG_ON(!port);
+ phys &= ~0x1F; /* mask out non-address bits */
+ n_desc = (phys - tx_desc_phys(port, 0)) / sizeof(struct desc);
+ BUG_ON(n_desc >= TX_DESCS);
+ desc = tx_desc_ptr(port, n_desc);
+ debug_desc(phys, desc);
+ struct net_device *dev = port->netdev;
+ struct net_device_stats *stats = hdlc_stats(dev);
+
+//#if DEBUG_TX
+// printk(KERN_DEBUG "hss_hdlc_txdone_irq1\n");
+//#endif
+// break;
+ if (port->tx_buff_tab[n_desc]) { /* not the draining packet */
+ stats->tx_packets++;
+ stats->tx_bytes += desc->pkt_len;
- dma_unmap_tx(port, desc);
+ dma_unmap_tx(port, desc);
#if DEBUG_TX
- printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n",
+ printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n",
dev->name, port->tx_buff_tab[n_desc]);
#endif
- free_buffer_irq(port->tx_buff_tab[n_desc]);
- port->tx_buff_tab[n_desc] = NULL;
+ free_buffer_irq(port->tx_buff_tab[n_desc]);
+ port->tx_buff_tab[n_desc] = NULL;
+ }
start = qmgr_stat_empty(port->plat->txreadyq);
- queue_put_desc(port->plat->txreadyq,
- tx_desc_phys(port, n_desc), desc);
+ queue_put_desc(port->plat->txreadyq, phys, desc);
if (start) {
#if DEBUG_TX
printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit"@@ -1142,6 +1324,16 @@
}
}
+static void hss_hdlc_txdone_irq0(void *pdev)
+{
+ hss_hdlc_txdone_irq(pdev, 0);
+}
+
+static void hss_hdlc_txdone_irq1(void *pdev)
+{
+ hss_hdlc_txdone_irq(pdev, 1);
+}
+
static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct port *port = dev_to_port(dev);@@ -1205,7 +1397,8 @@
desc->buf_len = desc->pkt_len = len;
wmb();
- queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc);
+ queue_put_desc(queue_ids[port->hss->id * 4 + port->hdlc].tx,
+ tx_desc_phys(port, n) | port->hdlc, desc);
dev->trans_start = jiffies;
if (qmgr_stat_empty(txreadyq)) {@@ -1234,15 +1427,17 @@
{
int err;
- err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0);
+ err = qmgr_request_queue(queue_ids[port->hss->id * 4 +