Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a371a07d authored by Koushik's avatar Koushik Committed by Jeff Garzik
Browse files

[PATCH] S2io: New link handling scheme for Xframe II



Hi,
The below patch implements a new "Link state change handling"
scheme supported by the Xframe II adapter. It also bumps up the
driver version to 2.0.2.0.

Signed-off-by: default avatarRavinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: default avatarRaghavendra Koushik <raghavendra.koushik@neterion.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent b6e3f982
Loading
Loading
Loading
Loading
+7 −1
Original line number Original line Diff line number Diff line
@@ -167,7 +167,11 @@ typedef struct _XENA_dev_config {
	u8 unused4[0x08];
	u8 unused4[0x08];


	u64 gpio_int_reg;
	u64 gpio_int_reg;
#define GPIO_INT_REG_LINK_DOWN                 BIT(1)
#define GPIO_INT_REG_LINK_UP                   BIT(2)
	u64 gpio_int_mask;
	u64 gpio_int_mask;
#define GPIO_INT_MASK_LINK_DOWN                BIT(1)
#define GPIO_INT_MASK_LINK_UP                  BIT(2)
	u64 gpio_alarms;
	u64 gpio_alarms;


	u8 unused5[0x38];
	u8 unused5[0x38];
@@ -279,8 +283,10 @@ typedef struct _XENA_dev_config {


	u64 gpio_control;
	u64 gpio_control;
#define GPIO_CTRL_GPIO_0		BIT(8)
#define GPIO_CTRL_GPIO_0		BIT(8)
	u64 misc_control;
#define MISC_LINK_STABILITY_PRD(val)   vBIT(val,29,3)


	u8 unused7_1[0x240 - 0x200];
	u8 unused7_1[0x240 - 0x208];


	u64 wreq_split_mask;
	u64 wreq_split_mask;
#define	WREQ_SPLIT_MASK_SET_MASK(val)	vBIT(val, 52, 12)
#define	WREQ_SPLIT_MASK_SET_MASK(val)	vBIT(val, 52, 12)
+114 −33
Original line number Original line Diff line number Diff line
@@ -67,7 +67,7 @@


/* S2io Driver name & version. */
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
static char s2io_driver_name[] = "Neterion";
static char s2io_driver_version[] = "Version 1.7.7";
static char s2io_driver_version[] = "Version 2.0.2.0";


static inline int RXD_IS_UP2DT(RxD_t *rxdp)
static inline int RXD_IS_UP2DT(RxD_t *rxdp)
{
{
@@ -1456,8 +1456,28 @@ static int init_nic(struct s2io_nic *nic)
		writeq(val64, &bar0->wreq_split_mask);
		writeq(val64, &bar0->wreq_split_mask);
	}
	}


	/* Setting Link stability period to 64 ms */ 
	if (nic->device_type == XFRAME_II_DEVICE) {
		val64 = MISC_LINK_STABILITY_PRD(3);
		writeq(val64, &bar0->misc_control);
	}

	return SUCCESS;
	return SUCCESS;
}
}
#define LINK_UP_DOWN_INTERRUPT		1
#define MAC_RMAC_ERR_TIMER		2

#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
#else
int s2io_link_fault_indication(nic_t *nic)
{
	if (nic->device_type == XFRAME_II_DEVICE)
		return LINK_UP_DOWN_INTERRUPT;
	else
		return MAC_RMAC_ERR_TIMER;
}
#endif


/**
/**
 *  en_dis_able_nic_intrs - Enable or Disable the interrupts
 *  en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1485,11 +1505,22 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
			temp64 &= ~((u64) val64);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->general_int_mask);
			writeq(temp64, &bar0->general_int_mask);
			/*
			/*
			 * Disabled all PCIX, Flash, MDIO, IIC and GPIO
			 * If Hercules adapter enable GPIO otherwise
			 * disabled all PCIX, Flash, MDIO, IIC and GPIO
			 * interrupts for now.
			 * interrupts for now.
			 * TODO
			 * TODO
			 */
			 */
			if (s2io_link_fault_indication(nic) ==
					LINK_UP_DOWN_INTERRUPT ) {
				temp64 = readq(&bar0->pic_int_mask);
				temp64 &= ~((u64) PIC_INT_GPIO);
				writeq(temp64, &bar0->pic_int_mask);
				temp64 = readq(&bar0->gpio_int_mask);
				temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
				writeq(temp64, &bar0->gpio_int_mask);
			} else {
				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
			}
			/*
			/*
			 * No MSI Support is available presently, so TTI and
			 * No MSI Support is available presently, so TTI and
			 * RTI interrupts are also disabled.
			 * RTI interrupts are also disabled.
@@ -1580,17 +1611,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
			writeq(temp64, &bar0->general_int_mask);
			writeq(temp64, &bar0->general_int_mask);
			/*
			/*
			 * All MAC block error interrupts are disabled for now
			 * All MAC block error interrupts are disabled for now
			 * except the link status change interrupt.
			 * TODO
			 * TODO
			 */
			 */
			val64 = MAC_INT_STATUS_RMAC_INT;
			temp64 = readq(&bar0->mac_int_mask);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->mac_int_mask);

			val64 = readq(&bar0->mac_rmac_err_mask);
			val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT);
			writeq(val64, &bar0->mac_rmac_err_mask);
		} else if (flag == DISABLE_INTRS) {
		} else if (flag == DISABLE_INTRS) {
			/*
			/*
			 * Disable MAC Intrs in the general intr mask register
			 * Disable MAC Intrs in the general intr mask register
@@ -1879,8 +1901,10 @@ static int start_nic(struct s2io_nic *nic)
	}
	}


	/*  Enable select interrupts */
	/*  Enable select interrupts */
	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | MC_INTR;
	    RX_MAC_INTR | MC_INTR;
	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
	interruptible |= TX_MAC_INTR | RX_MAC_INTR;

	en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
	en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);


	/*
	/*
@@ -2004,8 +2028,9 @@ static void stop_nic(struct s2io_nic *nic)
	config = &nic->config;
	config = &nic->config;


	/*  Disable all interrupts */
	/*  Disable all interrupts */
	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR |
	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | MC_INTR;
	    RX_MAC_INTR | MC_INTR;
	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);


	/*  Disable PRCs */
	/*  Disable PRCs */
@@ -2618,11 +2643,13 @@ static void alarm_intr_handler(struct s2io_nic *nic)
	register u64 val64 = 0, err_reg = 0;
	register u64 val64 = 0, err_reg = 0;


	/* Handling link status change error Intr */
	/* Handling link status change error Intr */
	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
		err_reg = readq(&bar0->mac_rmac_err_reg);
		err_reg = readq(&bar0->mac_rmac_err_reg);
		writeq(err_reg, &bar0->mac_rmac_err_reg);
		writeq(err_reg, &bar0->mac_rmac_err_reg);
		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
			schedule_work(&nic->set_link_task);
			schedule_work(&nic->set_link_task);
		}
		}
	}


	/* Handling Ecc errors */
	/* Handling Ecc errors */
	val64 = readq(&bar0->mc_err_reg);
	val64 = readq(&bar0->mc_err_reg);
@@ -2947,7 +2974,7 @@ int s2io_open(struct net_device *dev)
	 * Nic is initialized
	 * Nic is initialized
	 */
	 */
	netif_carrier_off(dev);
	netif_carrier_off(dev);
	sp->last_link_state = 0; /* Unkown link state */
	sp->last_link_state = LINK_DOWN;


	/* Initialize H/W and enable interrupts */
	/* Initialize H/W and enable interrupts */
	if (s2io_card_up(sp)) {
	if (s2io_card_up(sp)) {
@@ -3159,6 +3186,53 @@ s2io_alarm_handle(unsigned long data)
	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
}
}


static void s2io_txpic_intr_handle(nic_t *sp)
{
	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0;
	u64 val64;

	val64 = readq(&bar0->pic_int_status);
	if (val64 & PIC_INT_GPIO) {
		val64 = readq(&bar0->gpio_int_reg);
		if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
		    (val64 & GPIO_INT_REG_LINK_UP)) {
			val64 |=  GPIO_INT_REG_LINK_DOWN;
			val64 |= GPIO_INT_REG_LINK_UP;
			writeq(val64, &bar0->gpio_int_reg);
			goto masking;
		}

		if (((sp->last_link_state == LINK_UP) &&
			(val64 & GPIO_INT_REG_LINK_DOWN)) ||
		((sp->last_link_state == LINK_DOWN) &&
		(val64 & GPIO_INT_REG_LINK_UP))) {
			val64 = readq(&bar0->gpio_int_mask);
			val64 |=  GPIO_INT_MASK_LINK_DOWN;
			val64 |= GPIO_INT_MASK_LINK_UP;
			writeq(val64, &bar0->gpio_int_mask);
			s2io_set_link((unsigned long)sp);
		}
masking:
		if (sp->last_link_state == LINK_UP) {
			/*enable down interrupt */
			val64 = readq(&bar0->gpio_int_mask);
			/* unmasks link down intr */
			val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
			/* masks link up intr */
			val64 |= GPIO_INT_MASK_LINK_UP;
			writeq(val64, &bar0->gpio_int_mask);
		} else {
			/*enable UP Interrupt */
			val64 = readq(&bar0->gpio_int_mask);
			/* unmasks link up interrupt */
			val64 &= ~GPIO_INT_MASK_LINK_UP;
			/* masks link down interrupt */
			val64 |=  GPIO_INT_MASK_LINK_DOWN;
			writeq(val64, &bar0->gpio_int_mask);
		}
	}
}

/**
/**
 *  s2io_isr - ISR handler of the device .
 *  s2io_isr - ISR handler of the device .
 *  @irq: the irq of the device.
 *  @irq: the irq of the device.
@@ -3241,6 +3315,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
			tx_intr_handler(&mac_control->fifos[i]);
			tx_intr_handler(&mac_control->fifos[i]);
	}
	}


	if (reason & GEN_INTR_TXPIC)
		s2io_txpic_intr_handle(sp);
	/*
	/*
	 * If the Rx buffer count is below the panic threshold then
	 * If the Rx buffer count is below the panic threshold then
	 * reallocate the buffers from the interrupt handler itself,
	 * reallocate the buffers from the interrupt handler itself,
@@ -4644,11 +4720,13 @@ static void s2io_set_link(unsigned long data)
	}
	}


	subid = nic->pdev->subsystem_device;
	subid = nic->pdev->subsystem_device;
	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
		/*
		/*
		 * Allow a small delay for the NICs self initiated
		 * Allow a small delay for the NICs self initiated
		 * cleanup to complete.
		 * cleanup to complete.
		 */
		 */
		msleep(100);
		msleep(100);
	}


	val64 = readq(&bar0->adapter_status);
	val64 = readq(&bar0->adapter_status);
	if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
	if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {
@@ -4666,6 +4744,8 @@ static void s2io_set_link(unsigned long data)
				val64 |= ADAPTER_LED_ON;
				val64 |= ADAPTER_LED_ON;
				writeq(val64, &bar0->adapter_control);
				writeq(val64, &bar0->adapter_control);
			}
			}
			if (s2io_link_fault_indication(nic) ==
						MAC_RMAC_ERR_TIMER) {
				val64 = readq(&bar0->adapter_status);
				val64 = readq(&bar0->adapter_status);
				if (!LINK_IS_UP(val64)) {
				if (!LINK_IS_UP(val64)) {
					DBG_PRINT(ERR_DBG, "%s:", dev->name);
					DBG_PRINT(ERR_DBG, "%s:", dev->name);
@@ -4674,6 +4754,7 @@ static void s2io_set_link(unsigned long data)
					DBG_PRINT(ERR_DBG, "enabling ");
					DBG_PRINT(ERR_DBG, "enabling ");
					DBG_PRINT(ERR_DBG, "device \n");
					DBG_PRINT(ERR_DBG, "device \n");
				}
				}
			}
			if (nic->device_enabled_once == FALSE) {
			if (nic->device_enabled_once == FALSE) {
				nic->device_enabled_once = TRUE;
				nic->device_enabled_once = TRUE;
			}
			}