Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits) genetlink: fix netns vs. netlink table locking (2) 3c59x: Get rid of "Trying to free already-free IRQ" tunnel: eliminate recursion field ems_pci: fix size of CAN controllers BAR mapping for CPC-PCI v2 net: fix htmldocs sunrpc, clnt.c Phonet: error on broadcast sending (unimplemented) Phonet: fix race for port number in concurrent bind() pktgen: better scheduler friendliness pktgen: T_TERMINATE flag is unused ipv4: check optlen for IP_MULTICAST_IF option ath9k: Initialize txgain and rxgain for newer AR9287 chipsets. iwlagn: fix panic in iwl{5000,4965}_rx_reply_tx ath9k: Fix RFKILL bugs drivers/net/wireless: Use usb_endpoint_dir_out cfg80211: don't overwrite privacy setting wl12xx: fix kconfig/link errors rt2x00: fix the definition of rt2x00crypto_rx_insert_iv iwlwifi: reduce noise when skb allocation fails iwlwifi: do not send sync command while holding spinlock mac80211: fix DTIM setting ...
This commit is contained in:
commit
5c3cc2084d
93 changed files with 2620 additions and 2919 deletions
|
@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
|
||||||
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
|
void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* CAN Controller
|
||||||
|
* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
|
||||||
|
static struct resource can_resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.start = AT91SAM9263_BASE_CAN,
|
||||||
|
.end = AT91SAM9263_BASE_CAN + SZ_16K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
.start = AT91SAM9263_ID_CAN,
|
||||||
|
.end = AT91SAM9263_ID_CAN,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device at91sam9263_can_device = {
|
||||||
|
.name = "at91_can",
|
||||||
|
.id = -1,
|
||||||
|
.resource = can_resources,
|
||||||
|
.num_resources = ARRAY_SIZE(can_resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
void __init at91_add_device_can(struct at91_can_data *data)
|
||||||
|
{
|
||||||
|
at91_set_A_periph(AT91_PIN_PA13, 0); /* CANTX */
|
||||||
|
at91_set_A_periph(AT91_PIN_PA14, 0); /* CANRX */
|
||||||
|
at91sam9263_can_device.dev.platform_data = data;
|
||||||
|
|
||||||
|
platform_device_register(&at91sam9263_can_device);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void __init at91_add_device_can(struct at91_can_data *data) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
* LCD Controller
|
* LCD Controller
|
||||||
|
|
|
@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN
|
||||||
|
*/
|
||||||
|
static void sam9263ek_transceiver_switch(int on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
|
||||||
|
at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
|
||||||
|
} else {
|
||||||
|
at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
|
||||||
|
at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct at91_can_data ek_can_data = {
|
||||||
|
.transceiver_switch = sam9263ek_transceiver_switch,
|
||||||
|
};
|
||||||
|
|
||||||
static void __init ek_board_init(void)
|
static void __init ek_board_init(void)
|
||||||
{
|
{
|
||||||
|
@ -431,6 +448,8 @@ static void __init ek_board_init(void)
|
||||||
/* LEDs */
|
/* LEDs */
|
||||||
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
||||||
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
||||||
|
/* CAN */
|
||||||
|
at91_add_device_can(&ek_can_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
|
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
|
||||||
|
|
|
@ -188,6 +188,12 @@ extern void __init at91_add_device_isi(void);
|
||||||
/* Touchscreen Controller */
|
/* Touchscreen Controller */
|
||||||
extern void __init at91_add_device_tsadcc(void);
|
extern void __init at91_add_device_tsadcc(void);
|
||||||
|
|
||||||
|
/* CAN */
|
||||||
|
struct at91_can_data {
|
||||||
|
void (*transceiver_switch)(int on);
|
||||||
|
};
|
||||||
|
extern void __init at91_add_device_can(struct at91_can_data *data);
|
||||||
|
|
||||||
/* LEDs */
|
/* LEDs */
|
||||||
extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
|
extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
|
||||||
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
|
extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
|
||||||
|
|
|
@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
|
he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
|
||||||
CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
|
CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
|
||||||
if (he_dev->rbps_base == NULL) {
|
if (he_dev->rbps_base == NULL) {
|
||||||
hprintk("failed to alloc rbps\n");
|
hprintk("failed to alloc rbps_base\n");
|
||||||
return -ENOMEM;
|
goto out_destroy_rbps_pool;
|
||||||
}
|
}
|
||||||
memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
|
memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
|
||||||
he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
|
he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
|
||||||
|
if (he_dev->rbps_virt == NULL) {
|
||||||
|
hprintk("failed to alloc rbps_virt\n");
|
||||||
|
goto out_free_rbps_base;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
|
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
|
||||||
dma_addr_t dma_handle;
|
dma_addr_t dma_handle;
|
||||||
|
@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
|
|
||||||
cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
|
cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
|
||||||
if (cpuaddr == NULL)
|
if (cpuaddr == NULL)
|
||||||
return -ENOMEM;
|
goto out_free_rbps_virt;
|
||||||
|
|
||||||
he_dev->rbps_virt[i].virt = cpuaddr;
|
he_dev->rbps_virt[i].virt = cpuaddr;
|
||||||
he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
|
he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
|
||||||
|
@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
CONFIG_RBPL_BUFSIZE, 8, 0);
|
CONFIG_RBPL_BUFSIZE, 8, 0);
|
||||||
if (he_dev->rbpl_pool == NULL) {
|
if (he_dev->rbpl_pool == NULL) {
|
||||||
hprintk("unable to create rbpl pool\n");
|
hprintk("unable to create rbpl pool\n");
|
||||||
return -ENOMEM;
|
goto out_free_rbps_virt;
|
||||||
}
|
}
|
||||||
|
|
||||||
he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
|
he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
|
||||||
CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
|
CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
|
||||||
if (he_dev->rbpl_base == NULL) {
|
if (he_dev->rbpl_base == NULL) {
|
||||||
hprintk("failed to alloc rbpl\n");
|
hprintk("failed to alloc rbpl_base\n");
|
||||||
return -ENOMEM;
|
goto out_destroy_rbpl_pool;
|
||||||
}
|
}
|
||||||
memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
|
memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
|
||||||
he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
|
he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
|
||||||
|
if (he_dev->rbpl_virt == NULL) {
|
||||||
|
hprintk("failed to alloc rbpl_virt\n");
|
||||||
|
goto out_free_rbpl_base;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
|
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
|
||||||
dma_addr_t dma_handle;
|
dma_addr_t dma_handle;
|
||||||
|
@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
|
|
||||||
cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
|
cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
|
||||||
if (cpuaddr == NULL)
|
if (cpuaddr == NULL)
|
||||||
return -ENOMEM;
|
goto out_free_rbpl_virt;
|
||||||
|
|
||||||
he_dev->rbpl_virt[i].virt = cpuaddr;
|
he_dev->rbpl_virt[i].virt = cpuaddr;
|
||||||
he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
|
he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
|
||||||
|
@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
|
CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
|
||||||
if (he_dev->rbrq_base == NULL) {
|
if (he_dev->rbrq_base == NULL) {
|
||||||
hprintk("failed to allocate rbrq\n");
|
hprintk("failed to allocate rbrq\n");
|
||||||
return -ENOMEM;
|
goto out_free_rbpl_virt;
|
||||||
}
|
}
|
||||||
memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
|
memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
|
||||||
|
|
||||||
|
@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
|
CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
|
||||||
if (he_dev->tbrq_base == NULL) {
|
if (he_dev->tbrq_base == NULL) {
|
||||||
hprintk("failed to allocate tbrq\n");
|
hprintk("failed to allocate tbrq\n");
|
||||||
return -ENOMEM;
|
goto out_free_rbpq_base;
|
||||||
}
|
}
|
||||||
memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
|
memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
|
||||||
|
|
||||||
|
@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
|
||||||
he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
|
he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_free_rbpq_base:
|
||||||
|
pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
|
||||||
|
sizeof(struct he_rbrq), he_dev->rbrq_base,
|
||||||
|
he_dev->rbrq_phys);
|
||||||
|
i = CONFIG_RBPL_SIZE;
|
||||||
|
out_free_rbpl_virt:
|
||||||
|
while (--i)
|
||||||
|
pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
|
||||||
|
he_dev->rbps_base[i].phys);
|
||||||
|
kfree(he_dev->rbpl_virt);
|
||||||
|
|
||||||
|
out_free_rbpl_base:
|
||||||
|
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
|
||||||
|
sizeof(struct he_rbp), he_dev->rbpl_base,
|
||||||
|
he_dev->rbpl_phys);
|
||||||
|
out_destroy_rbpl_pool:
|
||||||
|
pci_pool_destroy(he_dev->rbpl_pool);
|
||||||
|
|
||||||
|
i = CONFIG_RBPL_SIZE;
|
||||||
|
out_free_rbps_virt:
|
||||||
|
while (--i)
|
||||||
|
pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
|
||||||
|
he_dev->rbpl_base[i].phys);
|
||||||
|
kfree(he_dev->rbps_virt);
|
||||||
|
|
||||||
|
out_free_rbps_base:
|
||||||
|
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
|
||||||
|
sizeof(struct he_rbp), he_dev->rbps_base,
|
||||||
|
he_dev->rbps_phys);
|
||||||
|
out_destroy_rbps_pool:
|
||||||
|
pci_pool_destroy(he_dev->rbps_pool);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit
|
static int __devinit
|
||||||
|
|
|
@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp)
|
||||||
SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
|
SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
|
||||||
SOLOS_ATTR_RO(InterleaveRDn)
|
SOLOS_ATTR_RO(InterleaveRDn)
|
||||||
SOLOS_ATTR_RO(InterleaveRUp)
|
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(ShowtimeStart)
|
||||||
SOLOS_ATTR_RO(ATURVendor)
|
SOLOS_ATTR_RO(ATURVendor)
|
||||||
SOLOS_ATTR_RO(ATUCCountry)
|
SOLOS_ATTR_RO(ATUCCountry)
|
||||||
|
@ -62,6 +66,13 @@ SOLOS_ATTR_RW(Defaults)
|
||||||
SOLOS_ATTR_RW(LineMode)
|
SOLOS_ATTR_RW(LineMode)
|
||||||
SOLOS_ATTR_RW(Profile)
|
SOLOS_ATTR_RW(Profile)
|
||||||
SOLOS_ATTR_RW(DetectNoise)
|
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(SupportedAnnexes)
|
||||||
SOLOS_ATTR_RO(Status)
|
SOLOS_ATTR_RO(Status)
|
||||||
SOLOS_ATTR_RO(TotalStart)
|
SOLOS_ATTR_RO(TotalStart)
|
||||||
|
|
|
@ -59,21 +59,29 @@
|
||||||
#define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
|
#define RX_DMA_ADDR(port) (0x30 + (4 * (port)))
|
||||||
|
|
||||||
#define DATA_RAM_SIZE 32768
|
#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 FPGA_PAGE 528 /* FPGA flash page size*/
|
||||||
#define SOLOS_PAGE 512 /* Solos flash page size*/
|
#define SOLOS_PAGE 512 /* Solos flash page size*/
|
||||||
#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
|
#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
|
||||||
#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos 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 RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
|
||||||
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
|
#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 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 reset = 0;
|
||||||
static int atmdebug = 0;
|
static int atmdebug = 0;
|
||||||
static int firmware_upgrade = 0;
|
static int firmware_upgrade = 0;
|
||||||
static int fpga_upgrade = 0;
|
static int fpga_upgrade = 0;
|
||||||
|
static int db_firmware_upgrade = 0;
|
||||||
|
static int db_fpga_upgrade = 0;
|
||||||
|
|
||||||
struct pkt_hdr {
|
struct pkt_hdr {
|
||||||
__le16 size;
|
__le16 size;
|
||||||
|
@ -116,6 +124,8 @@ struct solos_card {
|
||||||
wait_queue_head_t param_wq;
|
wait_queue_head_t param_wq;
|
||||||
wait_queue_head_t fw_wq;
|
wait_queue_head_t fw_wq;
|
||||||
int using_dma;
|
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(atmdebug, "Print ATM data");
|
||||||
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
||||||
MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA 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(reset, int, 0444);
|
||||||
module_param(atmdebug, int, 0644);
|
module_param(atmdebug, int, 0644);
|
||||||
module_param(firmware_upgrade, int, 0444);
|
module_param(firmware_upgrade, int, 0444);
|
||||||
module_param(fpga_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,
|
static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
|
||||||
struct atm_vcc *vcc);
|
struct atm_vcc *vcc);
|
||||||
|
@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||||
if (chip == 0) {
|
if (chip == 0) {
|
||||||
fw_name = "solos-FPGA.bin";
|
fw_name = "solos-FPGA.bin";
|
||||||
blocksize = FPGA_BLOCK;
|
blocksize = FPGA_BLOCK;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (chip == 1) {
|
||||||
fw_name = "solos-Firmware.bin";
|
fw_name = "solos-Firmware.bin";
|
||||||
blocksize = SOLOS_BLOCK;
|
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))
|
if (request_firmware(&fw, fw_name, &card->dev->dev))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
||||||
data32 = ioread32(card->config_regs + FPGA_MODE);
|
data32 = ioread32(card->config_regs + FPGA_MODE);
|
||||||
|
|
||||||
/* Set mode to Chip Erase */
|
/* Set mode to Chip Erase */
|
||||||
dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n",
|
if(chip == 0 || chip == 2)
|
||||||
chip?"Solos":"FPGA");
|
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);
|
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 */
|
/* Copy block to buffer, swapping each 16 bits */
|
||||||
for(i = 0; i < blocksize; i += 4) {
|
for(i = 0; i < blocksize; i += 4) {
|
||||||
uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
|
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 */
|
/* Specify block number and then trigger flash write */
|
||||||
|
@ -630,6 +671,10 @@ void solos_bh(unsigned long card_arg)
|
||||||
memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
|
memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
|
||||||
|
|
||||||
size = le16_to_cpu(header->size);
|
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);
|
skb = alloc_skb(size + 1, GFP_ATOMIC);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
|
@ -1094,12 +1139,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
fpga_ver = (data32 & 0x0000FFFF);
|
fpga_ver = (data32 & 0x0000FFFF);
|
||||||
major_ver = ((data32 & 0xFF000000) >> 24);
|
major_ver = ((data32 & 0xFF000000) >> 24);
|
||||||
minor_ver = ((data32 & 0x00FF0000) >> 16);
|
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",
|
dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
|
||||||
major_ver, minor_ver, fpga_ver);
|
major_ver, minor_ver, fpga_ver);
|
||||||
|
|
||||||
if (0 && fpga_ver > 27)
|
if (card->fpga_version >= DMA_SUPPORTED){
|
||||||
card->using_dma = 1;
|
card->using_dma = 1;
|
||||||
else {
|
} else {
|
||||||
|
card->using_dma = 0;
|
||||||
/* Set RX empty flag for all ports */
|
/* Set RX empty flag for all ports */
|
||||||
iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
|
iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
|
||||||
}
|
}
|
||||||
|
@ -1131,6 +1182,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
if (firmware_upgrade)
|
if (firmware_upgrade)
|
||||||
flash_upgrade(card, 1);
|
flash_upgrade(card, 1);
|
||||||
|
|
||||||
|
if (db_fpga_upgrade)
|
||||||
|
flash_upgrade(card, 2);
|
||||||
|
|
||||||
|
if (db_firmware_upgrade)
|
||||||
|
flash_upgrade(card, 3);
|
||||||
|
|
||||||
err = atm_init(card);
|
err = atm_init(card);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_irq;
|
goto out_free_irq;
|
||||||
|
|
|
@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
if (netif_running(dev)) {
|
if (netif_running(dev)) {
|
||||||
netif_device_detach(dev);
|
netif_device_detach(dev);
|
||||||
vortex_down(dev, 1);
|
vortex_down(dev, 1);
|
||||||
|
disable_irq(dev->irq);
|
||||||
}
|
}
|
||||||
pci_save_state(pdev);
|
pci_save_state(pdev);
|
||||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
|
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
|
||||||
free_irq(dev->irq, dev);
|
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||||
}
|
}
|
||||||
|
@ -839,18 +839,12 @@ static int vortex_resume(struct pci_dev *pdev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
pci_set_master(pdev);
|
pci_set_master(pdev);
|
||||||
if (request_irq(dev->irq, vp->full_bus_master_rx ?
|
|
||||||
&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
|
|
||||||
pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
|
|
||||||
pci_disable_device(pdev);
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
if (netif_running(dev)) {
|
if (netif_running(dev)) {
|
||||||
err = vortex_up(dev);
|
err = vortex_up(dev);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
else
|
enable_irq(dev->irq);
|
||||||
netif_device_attach(dev);
|
netif_device_attach(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
/* These identify the driver base version and may not be removed. */
|
/* These identify the driver base version and may not be removed. */
|
||||||
static char version[] =
|
static char version[] =
|
||||||
KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
|
DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
|
||||||
|
|
||||||
MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
|
MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
|
||||||
MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
|
MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
|
||||||
|
|
|
@ -1875,7 +1875,7 @@ config 68360_ENET
|
||||||
|
|
||||||
config FEC
|
config FEC
|
||||||
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
|
bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
|
||||||
depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35
|
depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25
|
||||||
help
|
help
|
||||||
Say Y here if you want to use the built-in 10/100 Fast ethernet
|
Say Y here if you want to use the built-in 10/100 Fast ethernet
|
||||||
controller on some Motorola ColdFire and Freescale i.MX processors.
|
controller on some Motorola ColdFire and Freescale i.MX processors.
|
||||||
|
|
|
@ -2296,7 +2296,7 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||||
u32 ctrl;
|
u32 ctrl;
|
||||||
u32 mac_ctrl_data;
|
u32 mac_ctrl_data;
|
||||||
u32 master_ctrl_data;
|
u32 master_ctrl_data;
|
||||||
u32 wol_ctrl_data;
|
u32 wol_ctrl_data = 0;
|
||||||
u16 mii_bmsr_data;
|
u16 mii_bmsr_data;
|
||||||
u16 save_autoneg_advertised;
|
u16 save_autoneg_advertised;
|
||||||
u16 mii_intr_status_data;
|
u16 mii_intr_status_data;
|
||||||
|
|
|
@ -75,6 +75,13 @@ config CAN_EMS_PCI
|
||||||
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
|
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
|
||||||
(http://www.ems-wuensche.de).
|
(http://www.ems-wuensche.de).
|
||||||
|
|
||||||
|
config CAN_EMS_USB
|
||||||
|
tristate "EMS CPC-USB/ARM7 CAN/USB interface"
|
||||||
|
depends on USB && CAN_DEV
|
||||||
|
---help---
|
||||||
|
This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
|
||||||
|
from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
|
||||||
|
|
||||||
config CAN_KVASER_PCI
|
config CAN_KVASER_PCI
|
||||||
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
|
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
|
||||||
depends on PCI && CAN_SJA1000
|
depends on PCI && CAN_SJA1000
|
||||||
|
@ -82,6 +89,12 @@ config CAN_KVASER_PCI
|
||||||
This driver is for the the PCIcanx and PCIcan cards (1, 2 or
|
This driver is for the the PCIcanx and PCIcan cards (1, 2 or
|
||||||
4 channel) from Kvaser (http://www.kvaser.com).
|
4 channel) from Kvaser (http://www.kvaser.com).
|
||||||
|
|
||||||
|
config CAN_AT91
|
||||||
|
tristate "Atmel AT91 onchip CAN controller"
|
||||||
|
depends on CAN && CAN_DEV && ARCH_AT91SAM9263
|
||||||
|
---help---
|
||||||
|
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
|
||||||
|
|
||||||
config CAN_DEBUG_DEVICES
|
config CAN_DEBUG_DEVICES
|
||||||
bool "CAN devices debugging messages"
|
bool "CAN devices debugging messages"
|
||||||
depends on CAN
|
depends on CAN
|
||||||
|
|
|
@ -7,6 +7,9 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
|
||||||
obj-$(CONFIG_CAN_DEV) += can-dev.o
|
obj-$(CONFIG_CAN_DEV) += can-dev.o
|
||||||
can-dev-y := dev.o
|
can-dev-y := dev.o
|
||||||
|
|
||||||
|
obj-y += usb/
|
||||||
|
|
||||||
obj-$(CONFIG_CAN_SJA1000) += sja1000/
|
obj-$(CONFIG_CAN_SJA1000) += sja1000/
|
||||||
|
obj-$(CONFIG_CAN_AT91) += at91_can.o
|
||||||
|
|
||||||
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
|
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
|
||||||
|
|
|
@ -94,12 +94,14 @@ struct ems_pci_card {
|
||||||
#define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
|
#define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
|
||||||
|
|
||||||
#define EMS_PCI_V1_BASE_BAR 1
|
#define EMS_PCI_V1_BASE_BAR 1
|
||||||
#define EMS_PCI_V1_MEM_SIZE 4096
|
#define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */
|
||||||
#define EMS_PCI_V2_BASE_BAR 2
|
#define EMS_PCI_V2_BASE_BAR 2
|
||||||
#define EMS_PCI_V2_MEM_SIZE 128
|
#define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */
|
||||||
#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
|
#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
|
||||||
#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */
|
#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */
|
||||||
|
|
||||||
|
#define EMS_PCI_BASE_SIZE 4096 /* size of controller area */
|
||||||
|
|
||||||
static struct pci_device_id ems_pci_tbl[] = {
|
static struct pci_device_id ems_pci_tbl[] = {
|
||||||
/* CPC-PCI v1 */
|
/* CPC-PCI v1 */
|
||||||
{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
|
{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
|
||||||
|
@ -224,7 +226,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
|
||||||
struct sja1000_priv *priv;
|
struct sja1000_priv *priv;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct ems_pci_card *card;
|
struct ems_pci_card *card;
|
||||||
int max_chan, mem_size, base_bar;
|
int max_chan, conf_size, base_bar;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
/* Enabling PCI device */
|
/* Enabling PCI device */
|
||||||
|
@ -251,22 +253,22 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
|
||||||
card->version = 2; /* CPC-PCI v2 */
|
card->version = 2; /* CPC-PCI v2 */
|
||||||
max_chan = EMS_PCI_V2_MAX_CHAN;
|
max_chan = EMS_PCI_V2_MAX_CHAN;
|
||||||
base_bar = EMS_PCI_V2_BASE_BAR;
|
base_bar = EMS_PCI_V2_BASE_BAR;
|
||||||
mem_size = EMS_PCI_V2_MEM_SIZE;
|
conf_size = EMS_PCI_V2_CONF_SIZE;
|
||||||
} else {
|
} else {
|
||||||
card->version = 1; /* CPC-PCI v1 */
|
card->version = 1; /* CPC-PCI v1 */
|
||||||
max_chan = EMS_PCI_V1_MAX_CHAN;
|
max_chan = EMS_PCI_V1_MAX_CHAN;
|
||||||
base_bar = EMS_PCI_V1_BASE_BAR;
|
base_bar = EMS_PCI_V1_BASE_BAR;
|
||||||
mem_size = EMS_PCI_V1_MEM_SIZE;
|
conf_size = EMS_PCI_V1_CONF_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remap configuration space and controller memory area */
|
/* Remap configuration space and controller memory area */
|
||||||
card->conf_addr = pci_iomap(pdev, 0, mem_size);
|
card->conf_addr = pci_iomap(pdev, 0, conf_size);
|
||||||
if (card->conf_addr == NULL) {
|
if (card->conf_addr == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto failure_cleanup;
|
goto failure_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
card->base_addr = pci_iomap(pdev, base_bar, mem_size);
|
card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE);
|
||||||
if (card->base_addr == NULL) {
|
if (card->base_addr == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto failure_cleanup;
|
goto failure_cleanup;
|
||||||
|
|
5
drivers/net/can/usb/Makefile
Normal file
5
drivers/net/can/usb/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#
|
||||||
|
# Makefile for the Linux Controller Area Network USB drivers.
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
|
1155
drivers/net/can/usb/ems_usb.c
Normal file
1155
drivers/net/can/usb/ems_usb.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -85,8 +85,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
|
||||||
|
|
||||||
cp->uio_dev = iminor(inode);
|
cp->uio_dev = iminor(inode);
|
||||||
|
|
||||||
cnic_shutdown_bnx2_rx_ring(dev);
|
|
||||||
|
|
||||||
cnic_init_bnx2_tx_ring(dev);
|
cnic_init_bnx2_tx_ring(dev);
|
||||||
cnic_init_bnx2_rx_ring(dev);
|
cnic_init_bnx2_rx_ring(dev);
|
||||||
|
|
||||||
|
@ -98,6 +96,8 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
|
||||||
struct cnic_dev *dev = uinfo->priv;
|
struct cnic_dev *dev = uinfo->priv;
|
||||||
struct cnic_local *cp = dev->cnic_priv;
|
struct cnic_local *cp = dev->cnic_priv;
|
||||||
|
|
||||||
|
cnic_shutdown_bnx2_rx_ring(dev);
|
||||||
|
|
||||||
cp->uio_dev = -1;
|
cp->uio_dev = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1109,7 +1109,7 @@ static int external_switch;
|
||||||
static int __devinit cpmac_probe(struct platform_device *pdev)
|
static int __devinit cpmac_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc, phy_id;
|
int rc, phy_id;
|
||||||
char mdio_bus_id[BUS_ID_SIZE];
|
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||||
struct resource *mem;
|
struct resource *mem;
|
||||||
struct cpmac_priv *priv;
|
struct cpmac_priv *priv;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
|
||||||
pdata = pdev->dev.platform_data;
|
pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
if (external_switch || dumb_switch) {
|
if (external_switch || dumb_switch) {
|
||||||
strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
|
strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
|
||||||
phy_id = pdev->id;
|
phy_id = pdev->id;
|
||||||
} else {
|
} else {
|
||||||
for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
|
for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
|
||||||
|
@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
|
||||||
continue;
|
continue;
|
||||||
if (!cpmac_mii->phy_map[phy_id])
|
if (!cpmac_mii->phy_map[phy_id])
|
||||||
continue;
|
continue;
|
||||||
strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
|
strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
|
||||||
priv->msg_enable = netif_msg_init(debug_level, 0xff);
|
priv->msg_enable = netif_msg_init(debug_level, 0xff);
|
||||||
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
|
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
|
||||||
|
|
||||||
snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
|
snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
|
||||||
|
|
||||||
priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
|
priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
|
||||||
PHY_INTERFACE_MODE_MII);
|
PHY_INTERFACE_MODE_MII);
|
||||||
|
|
|
@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = {
|
||||||
.ndo_poll_controller = ehea_netpoll,
|
.ndo_poll_controller = ehea_netpoll,
|
||||||
#endif
|
#endif
|
||||||
.ndo_get_stats = ehea_get_stats,
|
.ndo_get_stats = ehea_get_stats,
|
||||||
.ndo_change_mtu = eth_change_mtu,
|
|
||||||
.ndo_set_mac_address = ehea_set_mac_addr,
|
.ndo_set_mac_address = ehea_set_mac_addr,
|
||||||
.ndo_validate_addr = eth_validate_addr,
|
.ndo_validate_addr = eth_validate_addr,
|
||||||
.ndo_set_multicast_list = ehea_set_multicast_list,
|
.ndo_set_multicast_list = ehea_set_multicast_list,
|
||||||
|
|
|
@ -285,41 +285,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
|
||||||
wrfl();
|
wrfl();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* igb_update_mc_addr_list - Update Multicast addresses
|
|
||||||
* @hw: pointer to the HW structure
|
|
||||||
* @mc_addr_list: array of multicast addresses to program
|
|
||||||
* @mc_addr_count: number of multicast addresses to program
|
|
||||||
*
|
|
||||||
* Updates entire Multicast Table Array.
|
|
||||||
* The caller must have a packed mc_addr_list of multicast addresses.
|
|
||||||
**/
|
|
||||||
void igb_update_mc_addr_list(struct e1000_hw *hw,
|
|
||||||
u8 *mc_addr_list, u32 mc_addr_count)
|
|
||||||
{
|
|
||||||
u32 hash_value, hash_bit, hash_reg;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* clear mta_shadow */
|
|
||||||
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
|
|
||||||
|
|
||||||
/* update mta_shadow from mc_addr_list */
|
|
||||||
for (i = 0; (u32) i < mc_addr_count; i++) {
|
|
||||||
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
|
|
||||||
|
|
||||||
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
|
|
||||||
hash_bit = hash_value & 0x1F;
|
|
||||||
|
|
||||||
hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
|
|
||||||
mc_addr_list += (ETH_ALEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* replace the entire MTA table */
|
|
||||||
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
|
|
||||||
array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
|
|
||||||
wrfl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* igb_hash_mc_addr - Generate a multicast hash value
|
* igb_hash_mc_addr - Generate a multicast hash value
|
||||||
* @hw: pointer to the HW structure
|
* @hw: pointer to the HW structure
|
||||||
|
@ -329,7 +294,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
|
||||||
* the multicast filter table array address and new table value. See
|
* the multicast filter table array address and new table value. See
|
||||||
* igb_mta_set()
|
* igb_mta_set()
|
||||||
**/
|
**/
|
||||||
u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
|
static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
|
||||||
{
|
{
|
||||||
u32 hash_value, hash_mask;
|
u32 hash_value, hash_mask;
|
||||||
u8 bit_shift = 0;
|
u8 bit_shift = 0;
|
||||||
|
@ -391,6 +356,41 @@ u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
|
||||||
return hash_value;
|
return hash_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* igb_update_mc_addr_list - Update Multicast addresses
|
||||||
|
* @hw: pointer to the HW structure
|
||||||
|
* @mc_addr_list: array of multicast addresses to program
|
||||||
|
* @mc_addr_count: number of multicast addresses to program
|
||||||
|
*
|
||||||
|
* Updates entire Multicast Table Array.
|
||||||
|
* The caller must have a packed mc_addr_list of multicast addresses.
|
||||||
|
**/
|
||||||
|
void igb_update_mc_addr_list(struct e1000_hw *hw,
|
||||||
|
u8 *mc_addr_list, u32 mc_addr_count)
|
||||||
|
{
|
||||||
|
u32 hash_value, hash_bit, hash_reg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* clear mta_shadow */
|
||||||
|
memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
|
||||||
|
|
||||||
|
/* update mta_shadow from mc_addr_list */
|
||||||
|
for (i = 0; (u32) i < mc_addr_count; i++) {
|
||||||
|
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
|
||||||
|
|
||||||
|
hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
|
||||||
|
hash_bit = hash_value & 0x1F;
|
||||||
|
|
||||||
|
hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
|
||||||
|
mc_addr_list += (ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replace the entire MTA table */
|
||||||
|
for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
|
||||||
|
array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
|
||||||
|
wrfl();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* igb_clear_hw_cntrs_base - Clear base hardware counters
|
* igb_clear_hw_cntrs_base - Clear base hardware counters
|
||||||
* @hw: pointer to the HW structure
|
* @hw: pointer to the HW structure
|
||||||
|
|
|
@ -88,6 +88,5 @@ enum e1000_mng_mode {
|
||||||
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
|
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
|
||||||
|
|
||||||
extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
|
extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
|
||||||
extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -267,7 +267,8 @@ struct ixgbe_adapter {
|
||||||
enum ixgbe_fc_mode last_lfc_mode;
|
enum ixgbe_fc_mode last_lfc_mode;
|
||||||
|
|
||||||
/* Interrupt Throttle Rate */
|
/* Interrupt Throttle Rate */
|
||||||
u32 itr_setting;
|
u32 rx_itr_setting;
|
||||||
|
u32 tx_itr_setting;
|
||||||
u16 eitr_low;
|
u16 eitr_low;
|
||||||
u16 eitr_high;
|
u16 eitr_high;
|
||||||
|
|
||||||
|
@ -351,7 +352,8 @@ struct ixgbe_adapter {
|
||||||
struct ixgbe_hw_stats stats;
|
struct ixgbe_hw_stats stats;
|
||||||
|
|
||||||
/* Interrupt Throttle Rate */
|
/* Interrupt Throttle Rate */
|
||||||
u32 eitr_param;
|
u32 rx_eitr_param;
|
||||||
|
u32 tx_eitr_param;
|
||||||
|
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
u64 tx_busy;
|
u64 tx_busy;
|
||||||
|
|
|
@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
|
||||||
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
|
ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
|
||||||
|
|
||||||
/* only valid if in constant ITR mode */
|
/* only valid if in constant ITR mode */
|
||||||
switch (adapter->itr_setting) {
|
switch (adapter->rx_itr_setting) {
|
||||||
case 0:
|
case 0:
|
||||||
/* throttling disabled */
|
/* throttling disabled */
|
||||||
ec->rx_coalesce_usecs = 0;
|
ec->rx_coalesce_usecs = 0;
|
||||||
|
@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* fixed interrupt rate mode */
|
/* fixed interrupt rate mode */
|
||||||
ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
|
ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* only valid if in constant ITR mode */
|
||||||
|
switch (adapter->tx_itr_setting) {
|
||||||
|
case 0:
|
||||||
|
/* throttling disabled */
|
||||||
|
ec->tx_coalesce_usecs = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* dynamic ITR mode */
|
||||||
|
ec->tx_coalesce_usecs = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
struct ixgbe_q_vector *q_vector;
|
struct ixgbe_q_vector *q_vector;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* don't accept tx specific changes if we've got mixed RxTx vectors
|
||||||
|
* test and jump out here if needed before changing the rx numbers
|
||||||
|
*/
|
||||||
|
if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
|
||||||
|
adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (ec->tx_max_coalesced_frames_irq)
|
if (ec->tx_max_coalesced_frames_irq)
|
||||||
adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
|
adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
|
||||||
|
|
||||||
|
@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* store the value in ints/second */
|
/* store the value in ints/second */
|
||||||
adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
|
adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
|
||||||
|
|
||||||
/* static value of interrupt rate */
|
/* static value of interrupt rate */
|
||||||
adapter->itr_setting = adapter->eitr_param;
|
adapter->rx_itr_setting = adapter->rx_eitr_param;
|
||||||
/* clear the lower bit as its used for dynamic state */
|
/* clear the lower bit as its used for dynamic state */
|
||||||
adapter->itr_setting &= ~1;
|
adapter->rx_itr_setting &= ~1;
|
||||||
} else if (ec->rx_coalesce_usecs == 1) {
|
} else if (ec->rx_coalesce_usecs == 1) {
|
||||||
/* 1 means dynamic mode */
|
/* 1 means dynamic mode */
|
||||||
adapter->eitr_param = 20000;
|
adapter->rx_eitr_param = 20000;
|
||||||
adapter->itr_setting = 1;
|
adapter->rx_itr_setting = 1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* any other value means disable eitr, which is best
|
* any other value means disable eitr, which is best
|
||||||
* served by setting the interrupt rate very high
|
* served by setting the interrupt rate very high
|
||||||
*/
|
*/
|
||||||
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
|
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
|
||||||
adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
|
adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
|
||||||
else
|
else
|
||||||
adapter->eitr_param = IXGBE_MAX_INT_RATE;
|
adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
|
||||||
adapter->itr_setting = 0;
|
adapter->rx_itr_setting = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec->tx_coalesce_usecs > 1) {
|
||||||
|
/* check the limits */
|
||||||
|
if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
|
||||||
|
(1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* store the value in ints/second */
|
||||||
|
adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
|
||||||
|
|
||||||
|
/* static value of interrupt rate */
|
||||||
|
adapter->tx_itr_setting = adapter->tx_eitr_param;
|
||||||
|
|
||||||
|
/* clear the lower bit as its used for dynamic state */
|
||||||
|
adapter->tx_itr_setting &= ~1;
|
||||||
|
} else if (ec->tx_coalesce_usecs == 1) {
|
||||||
|
/* 1 means dynamic mode */
|
||||||
|
adapter->tx_eitr_param = 10000;
|
||||||
|
adapter->tx_itr_setting = 1;
|
||||||
|
} else {
|
||||||
|
adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
|
||||||
|
adapter->tx_itr_setting = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MSI/MSIx Interrupt Mode */
|
/* MSI/MSIx Interrupt Mode */
|
||||||
|
@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
|
||||||
for (i = 0; i < num_vectors; i++) {
|
for (i = 0; i < num_vectors; i++) {
|
||||||
q_vector = adapter->q_vector[i];
|
q_vector = adapter->q_vector[i];
|
||||||
if (q_vector->txr_count && !q_vector->rxr_count)
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
/* tx vector gets half the rate */
|
/* tx only */
|
||||||
q_vector->eitr = (adapter->eitr_param >> 1);
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
else
|
else
|
||||||
/* rx only or mixed */
|
/* rx only or mixed */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
/* Legacy Interrupt Mode */
|
/* Legacy Interrupt Mode */
|
||||||
} else {
|
} else {
|
||||||
q_vector = adapter->q_vector[0];
|
q_vector = adapter->q_vector[0];
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
|
||||||
r_idx + 1);
|
r_idx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if this is a tx only vector halve the interrupt rate */
|
|
||||||
if (q_vector->txr_count && !q_vector->rxr_count)
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
q_vector->eitr = (adapter->eitr_param >> 1);
|
/* tx only */
|
||||||
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
else if (q_vector->rxr_count)
|
else if (q_vector->rxr_count)
|
||||||
/* rx only */
|
/* rx or mixed */
|
||||||
q_vector->eitr = adapter->eitr_param;
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
|
|
||||||
ixgbe_write_eitr(q_vector);
|
ixgbe_write_eitr(q_vector);
|
||||||
}
|
}
|
||||||
|
@ -1359,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Rx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter,
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
@ -1420,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Rx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter,
|
ixgbe_irq_enable_queues(adapter,
|
||||||
|
@ -1458,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
|
||||||
if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
|
if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
|
||||||
work_done = budget;
|
work_done = budget;
|
||||||
|
|
||||||
/* If all Rx work done, exit the polling mode */
|
/* If all Tx work done, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->tx_itr_setting & 1)
|
||||||
ixgbe_set_itr_msix(q_vector);
|
ixgbe_set_itr_msix(q_vector);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
|
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
|
||||||
|
@ -1848,7 +1848,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
|
||||||
struct ixgbe_hw *hw = &adapter->hw;
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
|
IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
|
||||||
EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
|
EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
|
||||||
|
|
||||||
ixgbe_set_ivar(adapter, 0, 0, 0);
|
ixgbe_set_ivar(adapter, 0, 0, 0);
|
||||||
ixgbe_set_ivar(adapter, 1, 0, 0);
|
ixgbe_set_ivar(adapter, 1, 0, 0);
|
||||||
|
@ -1969,6 +1969,50 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
|
||||||
return mrqc;
|
return mrqc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ixgbe_configure_rscctl - enable RSC for the indicated ring
|
||||||
|
* @adapter: address of board private structure
|
||||||
|
* @index: index of ring to set
|
||||||
|
* @rx_buf_len: rx buffer length
|
||||||
|
**/
|
||||||
|
static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index,
|
||||||
|
int rx_buf_len)
|
||||||
|
{
|
||||||
|
struct ixgbe_ring *rx_ring;
|
||||||
|
struct ixgbe_hw *hw = &adapter->hw;
|
||||||
|
int j;
|
||||||
|
u32 rscctrl;
|
||||||
|
|
||||||
|
rx_ring = &adapter->rx_ring[index];
|
||||||
|
j = rx_ring->reg_idx;
|
||||||
|
rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
|
||||||
|
rscctrl |= IXGBE_RSCCTL_RSCEN;
|
||||||
|
/*
|
||||||
|
* we must limit the number of descriptors so that the
|
||||||
|
* total size of max desc * buf_len is not greater
|
||||||
|
* than 65535
|
||||||
|
*/
|
||||||
|
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
|
||||||
|
#if (MAX_SKB_FRAGS > 16)
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
|
||||||
|
#elif (MAX_SKB_FRAGS > 8)
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
|
||||||
|
#elif (MAX_SKB_FRAGS > 4)
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
|
||||||
|
#else
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (rx_buf_len < IXGBE_RXBUFFER_4096)
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
|
||||||
|
else if (rx_buf_len < IXGBE_RXBUFFER_8192)
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
|
||||||
|
else
|
||||||
|
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
|
||||||
|
}
|
||||||
|
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
|
* ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
|
||||||
* @adapter: board private structure
|
* @adapter: board private structure
|
||||||
|
@ -1990,7 +2034,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
|
||||||
u32 fctrl, hlreg0;
|
u32 fctrl, hlreg0;
|
||||||
u32 reta = 0, mrqc = 0;
|
u32 reta = 0, mrqc = 0;
|
||||||
u32 rdrxctl;
|
u32 rdrxctl;
|
||||||
u32 rscctrl;
|
|
||||||
int rx_buf_len;
|
int rx_buf_len;
|
||||||
|
|
||||||
/* Decide whether to use packet split mode or not */
|
/* Decide whether to use packet split mode or not */
|
||||||
|
@ -2148,36 +2191,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
|
||||||
|
|
||||||
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
|
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
|
||||||
/* Enable 82599 HW-RSC */
|
/* Enable 82599 HW-RSC */
|
||||||
for (i = 0; i < adapter->num_rx_queues; i++) {
|
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||||
rx_ring = &adapter->rx_ring[i];
|
ixgbe_configure_rscctl(adapter, i, rx_buf_len);
|
||||||
j = rx_ring->reg_idx;
|
|
||||||
rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
|
|
||||||
rscctrl |= IXGBE_RSCCTL_RSCEN;
|
|
||||||
/*
|
|
||||||
* we must limit the number of descriptors so that the
|
|
||||||
* total size of max desc * buf_len is not greater
|
|
||||||
* than 65535
|
|
||||||
*/
|
|
||||||
if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
|
|
||||||
#if (MAX_SKB_FRAGS > 16)
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
|
|
||||||
#elif (MAX_SKB_FRAGS > 8)
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
|
|
||||||
#elif (MAX_SKB_FRAGS > 4)
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
|
|
||||||
#else
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
if (rx_buf_len < IXGBE_RXBUFFER_4096)
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
|
|
||||||
else if (rx_buf_len < IXGBE_RXBUFFER_8192)
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
|
|
||||||
else
|
|
||||||
rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
|
|
||||||
}
|
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
|
|
||||||
}
|
|
||||||
/* Disable RSC for ACK packets */
|
/* Disable RSC for ACK packets */
|
||||||
IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
|
IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
|
||||||
(IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
|
(IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
|
||||||
|
@ -2926,6 +2942,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
||||||
|
|
||||||
ixgbe_napi_disable_all(adapter);
|
ixgbe_napi_disable_all(adapter);
|
||||||
|
|
||||||
|
clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
|
||||||
|
del_timer_sync(&adapter->sfp_timer);
|
||||||
del_timer_sync(&adapter->watchdog_timer);
|
del_timer_sync(&adapter->watchdog_timer);
|
||||||
cancel_work_sync(&adapter->watchdog_task);
|
cancel_work_sync(&adapter->watchdog_task);
|
||||||
|
|
||||||
|
@ -2989,7 +3007,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
|
||||||
/* If budget not fully consumed, exit the polling mode */
|
/* If budget not fully consumed, exit the polling mode */
|
||||||
if (work_done < budget) {
|
if (work_done < budget) {
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
if (adapter->itr_setting & 1)
|
if (adapter->rx_itr_setting & 1)
|
||||||
ixgbe_set_itr(adapter);
|
ixgbe_set_itr(adapter);
|
||||||
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
if (!test_bit(__IXGBE_DOWN, &adapter->state))
|
||||||
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
|
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
|
||||||
|
@ -3599,7 +3617,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
|
||||||
if (!q_vector)
|
if (!q_vector)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
q_vector->adapter = adapter;
|
q_vector->adapter = adapter;
|
||||||
q_vector->eitr = adapter->eitr_param;
|
if (q_vector->txr_count && !q_vector->rxr_count)
|
||||||
|
q_vector->eitr = adapter->tx_eitr_param;
|
||||||
|
else
|
||||||
|
q_vector->eitr = adapter->rx_eitr_param;
|
||||||
q_vector->v_idx = q_idx;
|
q_vector->v_idx = q_idx;
|
||||||
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
|
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
|
||||||
adapter->q_vector[q_idx] = q_vector;
|
adapter->q_vector[q_idx] = q_vector;
|
||||||
|
@ -3868,8 +3889,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
||||||
hw->fc.disable_fc_autoneg = false;
|
hw->fc.disable_fc_autoneg = false;
|
||||||
|
|
||||||
/* enable itr by default in dynamic mode */
|
/* enable itr by default in dynamic mode */
|
||||||
adapter->itr_setting = 1;
|
adapter->rx_itr_setting = 1;
|
||||||
adapter->eitr_param = 20000;
|
adapter->rx_eitr_param = 20000;
|
||||||
|
adapter->tx_itr_setting = 1;
|
||||||
|
adapter->tx_eitr_param = 10000;
|
||||||
|
|
||||||
/* set defaults for eitr in MegaBytes */
|
/* set defaults for eitr in MegaBytes */
|
||||||
adapter->eitr_low = 10;
|
adapter->eitr_low = 10;
|
||||||
|
|
|
@ -1469,6 +1469,7 @@ netxen_nic_resume(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
|
netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
|
||||||
|
return 0;
|
||||||
|
|
||||||
err_out_detach:
|
err_out_detach:
|
||||||
netxen_nic_detach(adapter);
|
netxen_nic_detach(adapter);
|
||||||
|
@ -1903,12 +1904,13 @@ static void netxen_tx_timeout_task(struct work_struct *work)
|
||||||
|
|
||||||
netif_wake_queue(adapter->netdev);
|
netif_wake_queue(adapter->netdev);
|
||||||
|
|
||||||
goto done;
|
clear_bit(__NX_RESETTING, &adapter->state);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
clear_bit(__NX_RESETTING, &adapter->state);
|
||||||
if (!netxen_nic_reset_context(adapter)) {
|
if (!netxen_nic_reset_context(adapter)) {
|
||||||
adapter->netdev->trans_start = jiffies;
|
adapter->netdev->trans_start = jiffies;
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* context reset failed, fall through for fw reset */
|
/* context reset failed, fall through for fw reset */
|
||||||
|
@ -1916,8 +1918,6 @@ static void netxen_tx_timeout_task(struct work_struct *work)
|
||||||
|
|
||||||
request_reset:
|
request_reset:
|
||||||
adapter->need_fw_reset = 1;
|
adapter->need_fw_reset = 1;
|
||||||
done:
|
|
||||||
clear_bit(__NX_RESETTING, &adapter->state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
|
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
|
||||||
|
|
|
@ -340,12 +340,11 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
|
||||||
base = &virt[hw_info[i].offset & (req.Size-1)];
|
base = &virt[hw_info[i].offset & (req.Size-1)];
|
||||||
if ((readb(base+0) == hw_info[i].a0) &&
|
if ((readb(base+0) == hw_info[i].a0) &&
|
||||||
(readb(base+2) == hw_info[i].a1) &&
|
(readb(base+2) == hw_info[i].a1) &&
|
||||||
(readb(base+4) == hw_info[i].a2))
|
(readb(base+4) == hw_info[i].a2)) {
|
||||||
break;
|
for (j = 0; j < 6; j++)
|
||||||
}
|
dev->dev_addr[j] = readb(base + (j<<1));
|
||||||
if (i < NR_INFO) {
|
break;
|
||||||
for (j = 0; j < 6; j++)
|
}
|
||||||
dev->dev_addr[j] = readb(base + (j<<1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iounmap(virt);
|
iounmap(virt);
|
||||||
|
|
|
@ -1497,7 +1497,6 @@ static int sky2_up(struct net_device *dev)
|
||||||
if (ramsize > 0) {
|
if (ramsize > 0) {
|
||||||
u32 rxspace;
|
u32 rxspace;
|
||||||
|
|
||||||
hw->flags |= SKY2_HW_RAM_BUFFER;
|
|
||||||
pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
|
pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
|
||||||
if (ramsize < 16)
|
if (ramsize < 16)
|
||||||
rxspace = ramsize / 2;
|
rxspace = ramsize / 2;
|
||||||
|
@ -2926,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
|
||||||
++hw->ports;
|
++hw->ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sky2_read8(hw, B2_E_0))
|
||||||
|
hw->flags |= SKY2_HW_RAM_BUFFER;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = {
|
||||||
.ndo_open = vnet_open,
|
.ndo_open = vnet_open,
|
||||||
.ndo_stop = vnet_close,
|
.ndo_stop = vnet_close,
|
||||||
.ndo_set_multicast_list = vnet_set_rx_mode,
|
.ndo_set_multicast_list = vnet_set_rx_mode,
|
||||||
.ndo_change_mtu = eth_change_mtu,
|
|
||||||
.ndo_set_mac_address = vnet_set_mac_addr,
|
.ndo_set_mac_address = vnet_set_mac_addr,
|
||||||
.ndo_validate_addr = eth_validate_addr,
|
.ndo_validate_addr = eth_validate_addr,
|
||||||
.ndo_tx_timeout = vnet_tx_timeout,
|
.ndo_tx_timeout = vnet_tx_timeout,
|
||||||
|
|
|
@ -946,8 +946,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||||
char *name;
|
char *name;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
|
||||||
err = -EINVAL;
|
|
||||||
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
err = security_tun_dev_create();
|
err = security_tun_dev_create();
|
||||||
|
@ -964,7 +962,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||||
flags |= TUN_TAP_DEV;
|
flags |= TUN_TAP_DEV;
|
||||||
name = "tap%d";
|
name = "tap%d";
|
||||||
} else
|
} else
|
||||||
goto failed;
|
return -EINVAL;
|
||||||
|
|
||||||
if (*ifr->ifr_name)
|
if (*ifr->ifr_name)
|
||||||
name = ifr->ifr_name;
|
name = ifr->ifr_name;
|
||||||
|
|
|
@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
|
||||||
int timeout)
|
int timeout)
|
||||||
{
|
{
|
||||||
struct usb_ctrlrequest *dr;
|
struct usb_ctrlrequest *dr;
|
||||||
|
int retval;
|
||||||
|
|
||||||
dbg("kaweth_control()");
|
dbg("kaweth_control()");
|
||||||
|
|
||||||
|
@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
dr->bRequestType= requesttype;
|
dr->bRequestType = requesttype;
|
||||||
dr->bRequest = request;
|
dr->bRequest = request;
|
||||||
dr->wValue = cpu_to_le16(value);
|
dr->wValue = cpu_to_le16(value);
|
||||||
dr->wIndex = cpu_to_le16(index);
|
dr->wIndex = cpu_to_le16(index);
|
||||||
dr->wLength = cpu_to_le16(size);
|
dr->wLength = cpu_to_le16(size);
|
||||||
|
|
||||||
return kaweth_internal_control_msg(kaweth->dev,
|
retval = kaweth_internal_control_msg(kaweth->dev,
|
||||||
pipe,
|
pipe,
|
||||||
dr,
|
dr,
|
||||||
data,
|
data,
|
||||||
size,
|
size,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
|
kfree(dr);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = {
|
||||||
.rx_fixup = smsc95xx_rx_fixup,
|
.rx_fixup = smsc95xx_rx_fixup,
|
||||||
.tx_fixup = smsc95xx_tx_fixup,
|
.tx_fixup = smsc95xx_tx_fixup,
|
||||||
.status = smsc95xx_status,
|
.status = smsc95xx_status,
|
||||||
.flags = FLAG_ETHER,
|
.flags = FLAG_ETHER | FLAG_SEND_ZLP,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct usb_device_id products[] = {
|
static const struct usb_device_id products[] = {
|
||||||
|
@ -1236,11 +1236,76 @@ static const struct usb_device_id products[] = {
|
||||||
USB_DEVICE(0x0424, 0x9500),
|
USB_DEVICE(0x0424, 0x9500),
|
||||||
.driver_info = (unsigned long) &smsc95xx_info,
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9505 USB Ethernet Device */
|
||||||
|
USB_DEVICE(0x0424, 0x9505),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500A USB Ethernet Device */
|
||||||
|
USB_DEVICE(0x0424, 0x9E00),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9505A USB Ethernet Device */
|
||||||
|
USB_DEVICE(0x0424, 0x9E01),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/* SMSC9512/9514 USB Hub & Ethernet Device */
|
/* SMSC9512/9514 USB Hub & Ethernet Device */
|
||||||
USB_DEVICE(0x0424, 0xec00),
|
USB_DEVICE(0x0424, 0xec00),
|
||||||
.driver_info = (unsigned long) &smsc95xx_info,
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500 USB Ethernet Device (SAL10) */
|
||||||
|
USB_DEVICE(0x0424, 0x9900),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9505 USB Ethernet Device (SAL10) */
|
||||||
|
USB_DEVICE(0x0424, 0x9901),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500A USB Ethernet Device (SAL10) */
|
||||||
|
USB_DEVICE(0x0424, 0x9902),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9505A USB Ethernet Device (SAL10) */
|
||||||
|
USB_DEVICE(0x0424, 0x9903),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
|
||||||
|
USB_DEVICE(0x0424, 0x9904),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500A USB Ethernet Device (HAL) */
|
||||||
|
USB_DEVICE(0x0424, 0x9905),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9505A USB Ethernet Device (HAL) */
|
||||||
|
USB_DEVICE(0x0424, 0x9906),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500 USB Ethernet Device (Alternate ID) */
|
||||||
|
USB_DEVICE(0x0424, 0x9907),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9500A USB Ethernet Device (Alternate ID) */
|
||||||
|
USB_DEVICE(0x0424, 0x9908),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
|
||||||
|
USB_DEVICE(0x0424, 0x9909),
|
||||||
|
.driver_info = (unsigned long) &smsc95xx_info,
|
||||||
|
},
|
||||||
{ }, /* END */
|
{ }, /* END */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(usb, products);
|
MODULE_DEVICE_TABLE(usb, products);
|
||||||
|
|
|
@ -1049,7 +1049,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
||||||
* NOTE: strictly conforming cdc-ether devices should expect
|
* NOTE: strictly conforming cdc-ether devices should expect
|
||||||
* the ZLP here, but ignore the one-byte packet.
|
* the ZLP here, but ignore the one-byte packet.
|
||||||
*/
|
*/
|
||||||
if ((length % dev->maxpacket) == 0) {
|
if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
|
||||||
urb->transfer_buffer_length++;
|
urb->transfer_buffer_length++;
|
||||||
if (skb_tailroom(skb)) {
|
if (skb_tailroom(skb)) {
|
||||||
skb->data[skb->len] = 0;
|
skb->data[skb->len] = 0;
|
||||||
|
|
|
@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
|
||||||
{ USB_DEVICE(0x0cf3, 0x9170) },
|
{ USB_DEVICE(0x0cf3, 0x9170) },
|
||||||
/* Atheros TG121N */
|
/* Atheros TG121N */
|
||||||
{ USB_DEVICE(0x0cf3, 0x1001) },
|
{ USB_DEVICE(0x0cf3, 0x1001) },
|
||||||
|
/* TP-Link TL-WN821N v2 */
|
||||||
|
{ USB_DEVICE(0x0cf3, 0x1002) },
|
||||||
/* Cace Airpcap NX */
|
/* Cace Airpcap NX */
|
||||||
{ USB_DEVICE(0xcace, 0x0300) },
|
{ USB_DEVICE(0xcace, 0x0300) },
|
||||||
/* D-Link DWA 160A */
|
/* D-Link DWA 160A */
|
||||||
|
|
|
@ -609,14 +609,24 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||||
AR_PHY_CH1_EXT_CCA,
|
AR_PHY_CH1_EXT_CCA,
|
||||||
AR_PHY_CH2_EXT_CCA
|
AR_PHY_CH2_EXT_CCA
|
||||||
};
|
};
|
||||||
u8 chainmask;
|
u8 chainmask, rx_chain_status;
|
||||||
|
|
||||||
|
rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
|
||||||
if (AR_SREV_9285(ah))
|
if (AR_SREV_9285(ah))
|
||||||
chainmask = 0x9;
|
chainmask = 0x9;
|
||||||
else if (AR_SREV_9280(ah) || AR_SREV_9287(ah))
|
else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
|
||||||
chainmask = 0x1B;
|
if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
|
||||||
else
|
chainmask = 0x1B;
|
||||||
chainmask = 0x3F;
|
else
|
||||||
|
chainmask = 0x09;
|
||||||
|
} else {
|
||||||
|
if (rx_chain_status & 0x4)
|
||||||
|
chainmask = 0x3F;
|
||||||
|
else if (rx_chain_status & 0x2)
|
||||||
|
chainmask = 0x1B;
|
||||||
|
else
|
||||||
|
chainmask = 0x09;
|
||||||
|
}
|
||||||
|
|
||||||
h = ah->nfCalHist;
|
h = ah->nfCalHist;
|
||||||
|
|
||||||
|
@ -697,6 +707,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
|
||||||
noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
|
noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
|
||||||
else if (AR_SREV_9285(ah))
|
else if (AR_SREV_9285(ah))
|
||||||
noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
|
noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
|
||||||
|
else if (AR_SREV_9287(ah))
|
||||||
|
noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
|
||||||
else
|
else
|
||||||
noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
|
noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
|
||||||
|
|
||||||
|
@ -924,6 +936,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
|
||||||
regVal |= (1 << (19 + i));
|
regVal |= (1 << (19 + i));
|
||||||
REG_WRITE(ah, 0x7834, regVal);
|
REG_WRITE(ah, 0x7834, regVal);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
regVal = REG_READ(ah, 0x7834);
|
||||||
regVal &= (~(0x1 << (19 + i)));
|
regVal &= (~(0x1 << (19 + i)));
|
||||||
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
|
reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
|
||||||
regVal |= (reg_field << (19 + i));
|
regVal |= (reg_field << (19 + i));
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern const struct ath9k_percal_data adc_init_dc_cal;
|
||||||
#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
|
#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
|
||||||
#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
|
#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
|
||||||
#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
|
#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
|
||||||
|
#define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118
|
||||||
#define AR_PHY_CCA_MAX_HIGH_VALUE -62
|
#define AR_PHY_CCA_MAX_HIGH_VALUE -62
|
||||||
#define AR_PHY_CCA_MIN_BAD_VALUE -140
|
#define AR_PHY_CCA_MIN_BAD_VALUE -140
|
||||||
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
|
#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3
|
||||||
|
|
|
@ -509,6 +509,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
||||||
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
|
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
|
||||||
eep->baseEepHeader.dacLpMode);
|
eep->baseEepHeader.dacLpMode);
|
||||||
|
|
||||||
|
udelay(100);
|
||||||
|
|
||||||
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
|
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
|
||||||
pModal->miscBits >> 2);
|
pModal->miscBits >> 2);
|
||||||
|
|
||||||
|
@ -902,7 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
|
||||||
u16 powerLimit)
|
u16 powerLimit)
|
||||||
{
|
{
|
||||||
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
|
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
|
||||||
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
|
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
|
||||||
|
|
||||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||||
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
|
||||||
|
|
|
@ -842,7 +842,7 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
|
||||||
|
|
||||||
static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
|
static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
if (AR_SREV_9287_11(ah))
|
if (AR_SREV_9287_11_OR_LATER(ah))
|
||||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||||
ar9287Modes_rx_gain_9287_1_1,
|
ar9287Modes_rx_gain_9287_1_1,
|
||||||
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
|
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
|
||||||
|
@ -853,7 +853,7 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||||
else if (AR_SREV_9280_20(ah))
|
else if (AR_SREV_9280_20(ah))
|
||||||
ath9k_hw_init_rxgain_ini(ah);
|
ath9k_hw_init_rxgain_ini(ah);
|
||||||
|
|
||||||
if (AR_SREV_9287_11(ah)) {
|
if (AR_SREV_9287_11_OR_LATER(ah)) {
|
||||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||||
ar9287Modes_tx_gain_9287_1_1,
|
ar9287Modes_tx_gain_9287_1_1,
|
||||||
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
|
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
|
||||||
|
@ -965,7 +965,7 @@ int ath9k_hw_init(struct ath_hw *ah)
|
||||||
ath9k_hw_init_mode_regs(ah);
|
ath9k_hw_init_mode_regs(ah);
|
||||||
|
|
||||||
if (ah->is_pciexpress)
|
if (ah->is_pciexpress)
|
||||||
ath9k_hw_configpcipowersave(ah, 0);
|
ath9k_hw_configpcipowersave(ah, 0, 0);
|
||||||
else
|
else
|
||||||
ath9k_hw_disablepcie(ah);
|
ath9k_hw_disablepcie(ah);
|
||||||
|
|
||||||
|
@ -1273,6 +1273,15 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
|
||||||
*/
|
*/
|
||||||
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
|
||||||
|
|
||||||
|
if (AR_SREV_9280_10_OR_LATER(ah)) {
|
||||||
|
val = REG_READ(ah, AR_PCU_MISC_MODE2) &
|
||||||
|
(~AR_PCU_MISC_MODE2_HWWAR1);
|
||||||
|
|
||||||
|
if (AR_SREV_9287_10_OR_LATER(ah))
|
||||||
|
val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
|
||||||
|
|
||||||
|
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
|
||||||
|
}
|
||||||
|
|
||||||
if (!AR_SREV_5416_20_OR_LATER(ah) ||
|
if (!AR_SREV_5416_20_OR_LATER(ah) ||
|
||||||
AR_SREV_9280_10_OR_LATER(ah))
|
AR_SREV_9280_10_OR_LATER(ah))
|
||||||
|
@ -1784,7 +1793,7 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
|
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
|
||||||
struct ath9k_channel *chan)
|
struct ath9k_channel *chan)
|
||||||
{
|
{
|
||||||
if (OLC_FOR_AR9280_20_LATER) {
|
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
|
||||||
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
|
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
|
||||||
return false;
|
return false;
|
||||||
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
|
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
|
||||||
|
@ -2338,6 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
struct ath9k_channel *curchan = ah->curchan;
|
struct ath9k_channel *curchan = ah->curchan;
|
||||||
u32 saveDefAntenna;
|
u32 saveDefAntenna;
|
||||||
u32 macStaId1;
|
u32 macStaId1;
|
||||||
|
u64 tsf = 0;
|
||||||
int i, rx_chainmask, r;
|
int i, rx_chainmask, r;
|
||||||
|
|
||||||
ah->extprotspacing = sc->ht_extprotspacing;
|
ah->extprotspacing = sc->ht_extprotspacing;
|
||||||
|
@ -2347,7 +2357,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (curchan)
|
if (curchan && !ah->chip_fullsleep)
|
||||||
ath9k_hw_getnf(ah, curchan);
|
ath9k_hw_getnf(ah, curchan);
|
||||||
|
|
||||||
if (bChannelChange &&
|
if (bChannelChange &&
|
||||||
|
@ -2356,8 +2366,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
(chan->channel != ah->curchan->channel) &&
|
(chan->channel != ah->curchan->channel) &&
|
||||||
((chan->channelFlags & CHANNEL_ALL) ==
|
((chan->channelFlags & CHANNEL_ALL) ==
|
||||||
(ah->curchan->channelFlags & CHANNEL_ALL)) &&
|
(ah->curchan->channelFlags & CHANNEL_ALL)) &&
|
||||||
(!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
|
!(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) ||
|
||||||
!IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) {
|
IS_CHAN_A_5MHZ_SPACED(ah->curchan))) {
|
||||||
|
|
||||||
if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
|
if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
|
||||||
ath9k_hw_loadnf(ah, ah->curchan);
|
ath9k_hw_loadnf(ah, ah->curchan);
|
||||||
|
@ -2372,6 +2382,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
|
|
||||||
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
|
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
|
||||||
|
|
||||||
|
/* For chips on which RTC reset is done, save TSF before it gets cleared */
|
||||||
|
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||||
|
tsf = ath9k_hw_gettsf64(ah);
|
||||||
|
|
||||||
saveLedState = REG_READ(ah, AR_CFG_LED) &
|
saveLedState = REG_READ(ah, AR_CFG_LED) &
|
||||||
(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
|
(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
|
||||||
AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
|
AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
|
||||||
|
@ -2398,6 +2412,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
udelay(50);
|
udelay(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restore TSF */
|
||||||
|
if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||||
|
ath9k_hw_settsf64(ah, tsf);
|
||||||
|
|
||||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||||
|
|
||||||
|
@ -3005,9 +3023,10 @@ void ath9k_ps_restore(struct ath_softc *sc)
|
||||||
* Programming the SerDes must go through the same 288 bit serial shift
|
* Programming the SerDes must go through the same 288 bit serial shift
|
||||||
* register as the other analog registers. Hence the 9 writes.
|
* register as the other analog registers. Hence the 9 writes.
|
||||||
*/
|
*/
|
||||||
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
|
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
if (ah->is_pciexpress != true)
|
if (ah->is_pciexpress != true)
|
||||||
return;
|
return;
|
||||||
|
@ -3017,84 +3036,113 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Nothing to do on restore for 11N */
|
/* Nothing to do on restore for 11N */
|
||||||
if (restore)
|
if (!restore) {
|
||||||
return;
|
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||||
|
/*
|
||||||
|
* AR9280 2.0 or later chips use SerDes values from the
|
||||||
|
* initvals.h initialized depending on chipset during
|
||||||
|
* ath9k_hw_init()
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
|
||||||
|
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
|
||||||
|
INI_RA(&ah->iniPcieSerdes, i, 1));
|
||||||
|
}
|
||||||
|
} else if (AR_SREV_9280(ah) &&
|
||||||
|
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
||||||
|
|
||||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
/* RX shut off when elecidle is asserted */
|
||||||
/*
|
REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
|
||||||
* AR9280 2.0 or later chips use SerDes values from the
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
|
||||||
* initvals.h initialized depending on chipset during
|
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
|
||||||
* ath9k_hw_init()
|
|
||||||
*/
|
/* Shut off CLKREQ active in L1 */
|
||||||
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
|
if (ah->config.pcie_clock_req)
|
||||||
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
|
||||||
INI_RA(&ah->iniPcieSerdes, i, 1));
|
else
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
|
||||||
|
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
|
||||||
|
|
||||||
|
/* Load the new settings */
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
||||||
|
|
||||||
|
/* RX shut off when elecidle is asserted */
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore ah->ah_config.pcie_clock_req setting for
|
||||||
|
* pre-AR9280 11n
|
||||||
|
*/
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
|
||||||
|
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
|
||||||
|
|
||||||
|
/* Load the new settings */
|
||||||
|
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||||
}
|
}
|
||||||
} else if (AR_SREV_9280(ah) &&
|
|
||||||
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
|
||||||
|
|
||||||
/* RX shut off when elecidle is asserted */
|
udelay(1000);
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
|
|
||||||
|
|
||||||
/* Shut off CLKREQ active in L1 */
|
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||||
if (ah->config.pcie_clock_req)
|
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
|
|
||||||
else
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
|
|
||||||
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
/* Several PCIe massages to ensure proper behaviour */
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
if (ah->config.pcie_waen) {
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
|
val = ah->config.pcie_waen;
|
||||||
|
if (!power_off)
|
||||||
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
|
} else {
|
||||||
|
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
||||||
|
AR_SREV_9287(ah)) {
|
||||||
|
val = AR9285_WA_DEFAULT;
|
||||||
|
if (!power_off)
|
||||||
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
|
} else if (AR_SREV_9280(ah)) {
|
||||||
|
/*
|
||||||
|
* On AR9280 chips bit 22 of 0x4004 needs to be
|
||||||
|
* set otherwise card may disappear.
|
||||||
|
*/
|
||||||
|
val = AR9280_WA_DEFAULT;
|
||||||
|
if (!power_off)
|
||||||
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
|
} else
|
||||||
|
val = AR_WA_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Load the new settings */
|
REG_WRITE(ah, AR_WA, val);
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
|
||||||
|
|
||||||
/* RX shut off when elecidle is asserted */
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ignore ah->ah_config.pcie_clock_req setting for
|
|
||||||
* pre-AR9280 11n
|
|
||||||
*/
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
|
|
||||||
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
|
|
||||||
|
|
||||||
/* Load the new settings */
|
|
||||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
udelay(1000);
|
if (power_off) {
|
||||||
|
|
||||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
|
||||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
|
||||||
|
|
||||||
/* Several PCIe massages to ensure proper behaviour */
|
|
||||||
if (ah->config.pcie_waen) {
|
|
||||||
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
|
|
||||||
} else {
|
|
||||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah))
|
|
||||||
REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
|
|
||||||
/*
|
/*
|
||||||
* On AR9280 chips bit 22 of 0x4004 needs to be set to
|
* Set PCIe workaround bits
|
||||||
* otherwise card may disappear.
|
* bit 14 in WA register (disable L1) should only
|
||||||
|
* be set when device enters D3 and be cleared
|
||||||
|
* when device comes back to D0.
|
||||||
*/
|
*/
|
||||||
else if (AR_SREV_9280(ah))
|
if (ah->config.pcie_waen) {
|
||||||
REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
|
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
||||||
else
|
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
||||||
REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
|
} else {
|
||||||
|
if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
||||||
|
AR_SREV_9287(ah)) &&
|
||||||
|
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
||||||
|
(AR_SREV_9280(ah) &&
|
||||||
|
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
||||||
|
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3652,15 +3700,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) ||
|
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
|
||||||
(ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
|
|
||||||
(ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
|
|
||||||
(ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
|
|
||||||
(ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
|
|
||||||
(ah->hw_version.macVersion == AR_SREV_VERSION_9285))
|
|
||||||
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
|
|
||||||
else
|
|
||||||
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
|
|
||||||
|
|
||||||
if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
|
if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
|
||||||
pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
|
pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
|
#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */
|
||||||
#define AH_TIME_QUANTUM 10
|
#define AH_TIME_QUANTUM 10
|
||||||
#define AR_KEYTABLE_SIZE 128
|
#define AR_KEYTABLE_SIZE 128
|
||||||
#define POWER_UP_TIME 200000
|
#define POWER_UP_TIME 10000
|
||||||
#define SPUR_RSSI_THRESH 40
|
#define SPUR_RSSI_THRESH 40
|
||||||
|
|
||||||
#define CAB_TIMEOUT_VAL 10
|
#define CAB_TIMEOUT_VAL 10
|
||||||
|
@ -650,7 +650,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
|
||||||
const struct ath9k_beacon_state *bs);
|
const struct ath9k_beacon_state *bs);
|
||||||
bool ath9k_hw_setpower(struct ath_hw *ah,
|
bool ath9k_hw_setpower(struct ath_hw *ah,
|
||||||
enum ath9k_power_mode mode);
|
enum ath9k_power_mode mode);
|
||||||
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
|
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off);
|
||||||
|
|
||||||
/* Interrupt Handling */
|
/* Interrupt Handling */
|
||||||
bool ath9k_hw_intrpend(struct ath_hw *ah);
|
bool ath9k_hw_intrpend(struct ath_hw *ah);
|
||||||
|
|
|
@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
ath9k_ps_wakeup(sc);
|
ath9k_ps_wakeup(sc);
|
||||||
ath9k_hw_configpcipowersave(ah, 0);
|
ath9k_hw_configpcipowersave(ah, 0, 0);
|
||||||
|
|
||||||
if (!ah->curchan)
|
if (!ah->curchan)
|
||||||
ah->curchan = ath_get_curchannel(sc, sc->hw);
|
ah->curchan = ath_get_curchannel(sc, sc->hw);
|
||||||
|
@ -1202,7 +1202,7 @@ void ath_radio_disable(struct ath_softc *sc)
|
||||||
spin_unlock_bh(&sc->sc_resetlock);
|
spin_unlock_bh(&sc->sc_resetlock);
|
||||||
|
|
||||||
ath9k_hw_phy_disable(ah);
|
ath9k_hw_phy_disable(ah);
|
||||||
ath9k_hw_configpcipowersave(ah, 1);
|
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||||
ath9k_ps_restore(sc);
|
ath9k_ps_restore(sc);
|
||||||
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
|
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
|
||||||
}
|
}
|
||||||
|
@ -1226,11 +1226,6 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
|
||||||
bool blocked = !!ath_is_rfkill_set(sc);
|
bool blocked = !!ath_is_rfkill_set(sc);
|
||||||
|
|
||||||
wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
|
wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
|
||||||
|
|
||||||
if (blocked)
|
|
||||||
ath_radio_disable(sc);
|
|
||||||
else
|
|
||||||
ath_radio_enable(sc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath_start_rfkill_poll(struct ath_softc *sc)
|
static void ath_start_rfkill_poll(struct ath_softc *sc)
|
||||||
|
@ -1260,6 +1255,7 @@ void ath_detach(struct ath_softc *sc)
|
||||||
DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
|
DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
|
||||||
|
|
||||||
ath_deinit_leds(sc);
|
ath_deinit_leds(sc);
|
||||||
|
wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
||||||
|
|
||||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||||
|
@ -1942,7 +1938,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
||||||
init_channel = ath_get_curchannel(sc, hw);
|
init_channel = ath_get_curchannel(sc, hw);
|
||||||
|
|
||||||
/* Reset SERDES registers */
|
/* Reset SERDES registers */
|
||||||
ath9k_hw_configpcipowersave(sc->sc_ah, 0);
|
ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The basic interface to setting the hardware in a good
|
* The basic interface to setting the hardware in a good
|
||||||
|
@ -2166,11 +2162,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||||
} else
|
} else
|
||||||
sc->rx.rxlink = NULL;
|
sc->rx.rxlink = NULL;
|
||||||
|
|
||||||
wiphy_rfkill_stop_polling(sc->hw->wiphy);
|
|
||||||
|
|
||||||
/* disable HAL and put h/w to sleep */
|
/* disable HAL and put h/w to sleep */
|
||||||
ath9k_hw_disable(sc->sc_ah);
|
ath9k_hw_disable(sc->sc_ah);
|
||||||
ath9k_hw_configpcipowersave(sc->sc_ah, 1);
|
ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1);
|
||||||
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
|
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
|
||||||
|
|
||||||
sc->sc_flags |= SC_OP_INVALID;
|
sc->sc_flags |= SC_OP_INVALID;
|
||||||
|
|
|
@ -676,8 +676,9 @@
|
||||||
#define AR_RC_HOSTIF 0x00000100
|
#define AR_RC_HOSTIF 0x00000100
|
||||||
|
|
||||||
#define AR_WA 0x4004
|
#define AR_WA 0x4004
|
||||||
|
#define AR_WA_D3_L1_DISABLE (1 << 14)
|
||||||
#define AR9285_WA_DEFAULT 0x004a05cb
|
#define AR9285_WA_DEFAULT 0x004a05cb
|
||||||
#define AR9280_WA_DEFAULT 0x0040073f
|
#define AR9280_WA_DEFAULT 0x0040073b
|
||||||
#define AR_WA_DEFAULT 0x0000073f
|
#define AR_WA_DEFAULT 0x0000073f
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,28 @@ config B43_PCMCIA
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config B43_SDIO
|
||||||
|
bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)"
|
||||||
|
depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL
|
||||||
|
select SSB_SDIOHOST
|
||||||
|
---help---
|
||||||
|
Broadcom 43xx device support for Soft-MAC SDIO devices.
|
||||||
|
|
||||||
|
With this config option you can drive Soft-MAC b43 cards with a
|
||||||
|
Secure Digital I/O interface.
|
||||||
|
This includes the WLAN daughter card found on the Nintendo Wii
|
||||||
|
video game console.
|
||||||
|
Note that this does not support Broadcom 43xx Full-MAC devices.
|
||||||
|
|
||||||
|
It's safe to select Y here, even if you don't have a B43 SDIO device.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
# Data transfers to the device via PIO
|
# Data transfers to the device via PIO
|
||||||
# This is only needed on PCMCIA devices. All others can do DMA properly.
|
# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
|
||||||
config B43_PIO
|
config B43_PIO
|
||||||
bool
|
bool
|
||||||
depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
|
depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
|
||||||
select SSB_BLOCKIO
|
select SSB_BLOCKIO
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO) += pio.o
|
||||||
b43-y += rfkill.o
|
b43-y += rfkill.o
|
||||||
b43-$(CONFIG_B43_LEDS) += leds.o
|
b43-$(CONFIG_B43_LEDS) += leds.o
|
||||||
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
||||||
|
b43-$(CONFIG_B43_SDIO) += sdio.o
|
||||||
b43-$(CONFIG_B43_DEBUG) += debugfs.o
|
b43-$(CONFIG_B43_DEBUG) += debugfs.o
|
||||||
|
|
||||||
obj-$(CONFIG_B43) += b43.o
|
obj-$(CONFIG_B43) += b43.o
|
||||||
|
|
|
@ -629,13 +629,6 @@ struct b43_wl {
|
||||||
* from the mac80211 subsystem. */
|
* from the mac80211 subsystem. */
|
||||||
u16 mac80211_initially_registered_queues;
|
u16 mac80211_initially_registered_queues;
|
||||||
|
|
||||||
/* R/W lock for data transmission.
|
|
||||||
* Transmissions on 2+ queues can run concurrently, but somebody else
|
|
||||||
* might sync with TX by write_lock_irqsave()'ing. */
|
|
||||||
rwlock_t tx_lock;
|
|
||||||
/* Lock for LEDs access. */
|
|
||||||
spinlock_t leds_lock;
|
|
||||||
|
|
||||||
/* We can only have one operating interface (802.11 core)
|
/* We can only have one operating interface (802.11 core)
|
||||||
* at a time. General information about this interface follows.
|
* at a time. General information about this interface follows.
|
||||||
*/
|
*/
|
||||||
|
@ -686,6 +679,9 @@ struct b43_wl {
|
||||||
struct work_struct tx_work;
|
struct work_struct tx_work;
|
||||||
/* Queue of packets to be transmitted. */
|
/* Queue of packets to be transmitted. */
|
||||||
struct sk_buff_head tx_queue;
|
struct sk_buff_head tx_queue;
|
||||||
|
|
||||||
|
/* The device LEDs. */
|
||||||
|
struct b43_leds leds;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The type of the firmware file. */
|
/* The type of the firmware file. */
|
||||||
|
@ -768,13 +764,10 @@ struct b43_wldev {
|
||||||
/* The device initialization status.
|
/* The device initialization status.
|
||||||
* Use b43_status() to query. */
|
* Use b43_status() to query. */
|
||||||
atomic_t __init_status;
|
atomic_t __init_status;
|
||||||
/* Saved init status for handling suspend. */
|
|
||||||
int suspend_init_status;
|
|
||||||
|
|
||||||
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
|
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
|
||||||
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
|
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
|
||||||
bool radio_hw_enable; /* saved state of radio hardware enabled state */
|
bool radio_hw_enable; /* saved state of radio hardware enabled state */
|
||||||
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
|
|
||||||
bool qos_enabled; /* TRUE, if QoS is used. */
|
bool qos_enabled; /* TRUE, if QoS is used. */
|
||||||
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
|
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
|
||||||
|
|
||||||
|
@ -794,12 +787,6 @@ struct b43_wldev {
|
||||||
/* Various statistics about the physical device. */
|
/* Various statistics about the physical device. */
|
||||||
struct b43_stats stats;
|
struct b43_stats stats;
|
||||||
|
|
||||||
/* The device LEDs. */
|
|
||||||
struct b43_led led_tx;
|
|
||||||
struct b43_led led_rx;
|
|
||||||
struct b43_led led_assoc;
|
|
||||||
struct b43_led led_radio;
|
|
||||||
|
|
||||||
/* Reason code of the last interrupt. */
|
/* Reason code of the last interrupt. */
|
||||||
u32 irq_reason;
|
u32 irq_reason;
|
||||||
u32 dma_reason[6];
|
u32 dma_reason[6];
|
||||||
|
@ -830,6 +817,10 @@ struct b43_wldev {
|
||||||
/* Debugging stuff follows. */
|
/* Debugging stuff follows. */
|
||||||
#ifdef CONFIG_B43_DEBUG
|
#ifdef CONFIG_B43_DEBUG
|
||||||
struct b43_dfsentry *dfsentry;
|
struct b43_dfsentry *dfsentry;
|
||||||
|
unsigned int irq_count;
|
||||||
|
unsigned int irq_bit_count[32];
|
||||||
|
unsigned int tx_count;
|
||||||
|
unsigned int rx_count;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
|
||||||
add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
|
add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
|
||||||
add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
|
add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
|
||||||
add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
|
add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
|
||||||
|
add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0);
|
||||||
|
|
||||||
#undef add_dyn_dbg
|
#undef add_dyn_dbg
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
|
||||||
B43_DBG_LO,
|
B43_DBG_LO,
|
||||||
B43_DBG_FIRMWARE,
|
B43_DBG_FIRMWARE,
|
||||||
B43_DBG_KEYS,
|
B43_DBG_KEYS,
|
||||||
|
B43_DBG_VERBOSESTATS,
|
||||||
__B43_NR_DYNDBG,
|
__B43_NR_DYNDBG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||||
ring->nr_failed_tx_packets++;
|
ring->nr_failed_tx_packets++;
|
||||||
ring->nr_total_packet_tries += status->frame_count;
|
ring->nr_total_packet_tries += status->frame_count;
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
|
ieee80211_tx_status(dev->wl->hw, meta->skb);
|
||||||
|
|
||||||
/* skb is freed by ieee80211_tx_status_irqsafe() */
|
/* skb is freed by ieee80211_tx_status() */
|
||||||
meta->skb = NULL;
|
meta->skb = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* No need to call free_descriptor_buffer here, as
|
/* No need to call free_descriptor_buffer here, as
|
||||||
|
|
|
@ -34,35 +34,75 @@
|
||||||
static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
|
static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
|
||||||
bool activelow)
|
bool activelow)
|
||||||
{
|
{
|
||||||
struct b43_wl *wl = dev->wl;
|
|
||||||
unsigned long flags;
|
|
||||||
u16 ctl;
|
u16 ctl;
|
||||||
|
|
||||||
spin_lock_irqsave(&wl->leds_lock, flags);
|
|
||||||
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
|
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
|
||||||
if (activelow)
|
if (activelow)
|
||||||
ctl &= ~(1 << led_index);
|
ctl &= ~(1 << led_index);
|
||||||
else
|
else
|
||||||
ctl |= (1 << led_index);
|
ctl |= (1 << led_index);
|
||||||
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
|
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
|
||||||
spin_unlock_irqrestore(&wl->leds_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
|
static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
|
||||||
bool activelow)
|
bool activelow)
|
||||||
{
|
{
|
||||||
struct b43_wl *wl = dev->wl;
|
|
||||||
unsigned long flags;
|
|
||||||
u16 ctl;
|
u16 ctl;
|
||||||
|
|
||||||
spin_lock_irqsave(&wl->leds_lock, flags);
|
|
||||||
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
|
ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
|
||||||
if (activelow)
|
if (activelow)
|
||||||
ctl |= (1 << led_index);
|
ctl |= (1 << led_index);
|
||||||
else
|
else
|
||||||
ctl &= ~(1 << led_index);
|
ctl &= ~(1 << led_index);
|
||||||
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
|
b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
|
||||||
spin_unlock_irqrestore(&wl->leds_lock, flags);
|
}
|
||||||
|
|
||||||
|
static void b43_led_update(struct b43_wldev *dev,
|
||||||
|
struct b43_led *led)
|
||||||
|
{
|
||||||
|
bool radio_enabled;
|
||||||
|
bool turn_on;
|
||||||
|
|
||||||
|
if (!led->wl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
|
||||||
|
|
||||||
|
/* The led->state read is racy, but we don't care. In case we raced
|
||||||
|
* with the brightness_set handler, we will be called again soon
|
||||||
|
* to fixup our state. */
|
||||||
|
if (radio_enabled)
|
||||||
|
turn_on = atomic_read(&led->state) != LED_OFF;
|
||||||
|
else
|
||||||
|
turn_on = 0;
|
||||||
|
if (turn_on == led->hw_state)
|
||||||
|
return;
|
||||||
|
led->hw_state = turn_on;
|
||||||
|
|
||||||
|
if (turn_on)
|
||||||
|
b43_led_turn_on(dev, led->index, led->activelow);
|
||||||
|
else
|
||||||
|
b43_led_turn_off(dev, led->index, led->activelow);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void b43_leds_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct b43_leds *leds = container_of(work, struct b43_leds, work);
|
||||||
|
struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
|
||||||
|
struct b43_wldev *dev;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
|
dev = wl->current_dev;
|
||||||
|
if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
b43_led_update(dev, &wl->leds.led_tx);
|
||||||
|
b43_led_update(dev, &wl->leds.led_rx);
|
||||||
|
b43_led_update(dev, &wl->leds.led_radio);
|
||||||
|
b43_led_update(dev, &wl->leds.led_assoc);
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback from the LED subsystem. */
|
/* Callback from the LED subsystem. */
|
||||||
|
@ -70,21 +110,12 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,
|
||||||
enum led_brightness brightness)
|
enum led_brightness brightness)
|
||||||
{
|
{
|
||||||
struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
|
struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
|
||||||
struct b43_wldev *dev = led->dev;
|
struct b43_wl *wl = led->wl;
|
||||||
bool radio_enabled;
|
|
||||||
|
|
||||||
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED))
|
if (likely(!wl->leds.stop)) {
|
||||||
return;
|
atomic_set(&led->state, brightness);
|
||||||
|
ieee80211_queue_work(wl->hw, &wl->leds.work);
|
||||||
/* Checking the radio-enabled status here is slightly racy,
|
}
|
||||||
* but we want to avoid the locking overhead and we don't care
|
|
||||||
* whether the LED has the wrong state for a second. */
|
|
||||||
radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
|
|
||||||
|
|
||||||
if (brightness == LED_OFF || !radio_enabled)
|
|
||||||
b43_led_turn_off(dev, led->index, led->activelow);
|
|
||||||
else
|
|
||||||
b43_led_turn_on(dev, led->index, led->activelow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
|
static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
|
||||||
|
@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
b43_led_turn_off(dev, led_index, activelow);
|
if (led->wl)
|
||||||
if (led->dev)
|
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
if (!default_trigger)
|
if (!default_trigger)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
led->dev = dev;
|
led->wl = dev->wl;
|
||||||
led->index = led_index;
|
led->index = led_index;
|
||||||
led->activelow = activelow;
|
led->activelow = activelow;
|
||||||
strncpy(led->name, name, sizeof(led->name));
|
strncpy(led->name, name, sizeof(led->name));
|
||||||
|
atomic_set(&led->state, 0);
|
||||||
|
|
||||||
led->led_dev.name = led->name;
|
led->led_dev.name = led->name;
|
||||||
led->led_dev.default_trigger = default_trigger;
|
led->led_dev.default_trigger = default_trigger;
|
||||||
|
@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
|
||||||
err = led_classdev_register(dev->dev->dev, &led->led_dev);
|
err = led_classdev_register(dev->dev->dev, &led->led_dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
|
b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
|
||||||
led->dev = NULL;
|
led->wl = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_unregister_led(struct b43_led *led)
|
static void b43_unregister_led(struct b43_led *led)
|
||||||
{
|
{
|
||||||
if (!led->dev)
|
if (!led->wl)
|
||||||
return;
|
return;
|
||||||
led_classdev_unregister(&led->led_dev);
|
led_classdev_unregister(&led->led_dev);
|
||||||
b43_led_turn_off(led->dev, led->index, led->activelow);
|
led->wl = NULL;
|
||||||
led->dev = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_map_led(struct b43_wldev *dev,
|
static void b43_map_led(struct b43_wldev *dev,
|
||||||
|
@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev,
|
||||||
* generic LED triggers. */
|
* generic LED triggers. */
|
||||||
switch (behaviour) {
|
switch (behaviour) {
|
||||||
case B43_LED_INACTIVE:
|
case B43_LED_INACTIVE:
|
||||||
break;
|
|
||||||
case B43_LED_OFF:
|
case B43_LED_OFF:
|
||||||
b43_led_turn_off(dev, led_index, activelow);
|
|
||||||
break;
|
|
||||||
case B43_LED_ON:
|
case B43_LED_ON:
|
||||||
b43_led_turn_on(dev, led_index, activelow);
|
|
||||||
break;
|
break;
|
||||||
case B43_LED_ACTIVITY:
|
case B43_LED_ACTIVITY:
|
||||||
case B43_LED_TRANSFER:
|
case B43_LED_TRANSFER:
|
||||||
case B43_LED_APTRANSFER:
|
case B43_LED_APTRANSFER:
|
||||||
snprintf(name, sizeof(name),
|
snprintf(name, sizeof(name),
|
||||||
"b43-%s::tx", wiphy_name(hw->wiphy));
|
"b43-%s::tx", wiphy_name(hw->wiphy));
|
||||||
b43_register_led(dev, &dev->led_tx, name,
|
b43_register_led(dev, &dev->wl->leds.led_tx, name,
|
||||||
ieee80211_get_tx_led_name(hw),
|
ieee80211_get_tx_led_name(hw),
|
||||||
led_index, activelow);
|
led_index, activelow);
|
||||||
snprintf(name, sizeof(name),
|
snprintf(name, sizeof(name),
|
||||||
"b43-%s::rx", wiphy_name(hw->wiphy));
|
"b43-%s::rx", wiphy_name(hw->wiphy));
|
||||||
b43_register_led(dev, &dev->led_rx, name,
|
b43_register_led(dev, &dev->wl->leds.led_rx, name,
|
||||||
ieee80211_get_rx_led_name(hw),
|
ieee80211_get_rx_led_name(hw),
|
||||||
led_index, activelow);
|
led_index, activelow);
|
||||||
break;
|
break;
|
||||||
|
@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev,
|
||||||
case B43_LED_MODE_BG:
|
case B43_LED_MODE_BG:
|
||||||
snprintf(name, sizeof(name),
|
snprintf(name, sizeof(name),
|
||||||
"b43-%s::radio", wiphy_name(hw->wiphy));
|
"b43-%s::radio", wiphy_name(hw->wiphy));
|
||||||
b43_register_led(dev, &dev->led_radio, name,
|
b43_register_led(dev, &dev->wl->leds.led_radio, name,
|
||||||
ieee80211_get_radio_led_name(hw),
|
ieee80211_get_radio_led_name(hw),
|
||||||
led_index, activelow);
|
led_index, activelow);
|
||||||
/* Sync the RF-kill LED state with radio and switch states. */
|
|
||||||
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
|
|
||||||
b43_led_turn_on(dev, led_index, activelow);
|
|
||||||
break;
|
break;
|
||||||
case B43_LED_WEIRD:
|
case B43_LED_WEIRD:
|
||||||
case B43_LED_ASSOC:
|
case B43_LED_ASSOC:
|
||||||
snprintf(name, sizeof(name),
|
snprintf(name, sizeof(name),
|
||||||
"b43-%s::assoc", wiphy_name(hw->wiphy));
|
"b43-%s::assoc", wiphy_name(hw->wiphy));
|
||||||
b43_register_led(dev, &dev->led_assoc, name,
|
b43_register_led(dev, &dev->wl->leds.led_assoc, name,
|
||||||
ieee80211_get_assoc_led_name(hw),
|
ieee80211_get_assoc_led_name(hw),
|
||||||
led_index, activelow);
|
led_index, activelow);
|
||||||
break;
|
break;
|
||||||
|
@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void b43_leds_init(struct b43_wldev *dev)
|
static void b43_led_get_sprominfo(struct b43_wldev *dev,
|
||||||
|
unsigned int led_index,
|
||||||
|
enum b43_led_behaviour *behaviour,
|
||||||
|
bool *activelow)
|
||||||
{
|
{
|
||||||
struct ssb_bus *bus = dev->dev->bus;
|
struct ssb_bus *bus = dev->dev->bus;
|
||||||
u8 sprom[4];
|
u8 sprom[4];
|
||||||
int i;
|
|
||||||
enum b43_led_behaviour behaviour;
|
|
||||||
bool activelow;
|
|
||||||
|
|
||||||
sprom[0] = bus->sprom.gpio0;
|
sprom[0] = bus->sprom.gpio0;
|
||||||
sprom[1] = bus->sprom.gpio1;
|
sprom[1] = bus->sprom.gpio1;
|
||||||
sprom[2] = bus->sprom.gpio2;
|
sprom[2] = bus->sprom.gpio2;
|
||||||
sprom[3] = bus->sprom.gpio3;
|
sprom[3] = bus->sprom.gpio3;
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
if (sprom[led_index] == 0xFF) {
|
||||||
if (sprom[i] == 0xFF) {
|
/* There is no LED information in the SPROM
|
||||||
/* There is no LED information in the SPROM
|
* for this LED. Hardcode it here. */
|
||||||
* for this LED. Hardcode it here. */
|
*activelow = 0;
|
||||||
activelow = 0;
|
switch (led_index) {
|
||||||
switch (i) {
|
case 0:
|
||||||
case 0:
|
*behaviour = B43_LED_ACTIVITY;
|
||||||
behaviour = B43_LED_ACTIVITY;
|
*activelow = 1;
|
||||||
activelow = 1;
|
if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
|
||||||
if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
|
*behaviour = B43_LED_RADIO_ALL;
|
||||||
behaviour = B43_LED_RADIO_ALL;
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
*behaviour = B43_LED_RADIO_B;
|
||||||
behaviour = B43_LED_RADIO_B;
|
if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
|
||||||
if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
|
*behaviour = B43_LED_ASSOC;
|
||||||
behaviour = B43_LED_ASSOC;
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
*behaviour = B43_LED_RADIO_A;
|
||||||
behaviour = B43_LED_RADIO_A;
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
*behaviour = B43_LED_OFF;
|
||||||
behaviour = B43_LED_OFF;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
B43_WARN_ON(1);
|
||||||
B43_WARN_ON(1);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
behaviour = sprom[i] & B43_LED_BEHAVIOUR;
|
|
||||||
activelow = !!(sprom[i] & B43_LED_ACTIVELOW);
|
|
||||||
}
|
}
|
||||||
b43_map_led(dev, i, behaviour, activelow);
|
} else {
|
||||||
|
*behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
|
||||||
|
*activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void b43_leds_init(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_led *led;
|
||||||
|
unsigned int i;
|
||||||
|
enum b43_led_behaviour behaviour;
|
||||||
|
bool activelow;
|
||||||
|
|
||||||
|
/* Sync the RF-kill LED state (if we have one) with radio and switch states. */
|
||||||
|
led = &dev->wl->leds.led_radio;
|
||||||
|
if (led->wl) {
|
||||||
|
if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
|
||||||
|
b43_led_turn_on(dev, led->index, led->activelow);
|
||||||
|
led->hw_state = 1;
|
||||||
|
atomic_set(&led->state, 1);
|
||||||
|
} else {
|
||||||
|
b43_led_turn_off(dev, led->index, led->activelow);
|
||||||
|
led->hw_state = 0;
|
||||||
|
atomic_set(&led->state, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize TX/RX/ASSOC leds */
|
||||||
|
led = &dev->wl->leds.led_tx;
|
||||||
|
if (led->wl) {
|
||||||
|
b43_led_turn_off(dev, led->index, led->activelow);
|
||||||
|
led->hw_state = 0;
|
||||||
|
atomic_set(&led->state, 0);
|
||||||
|
}
|
||||||
|
led = &dev->wl->leds.led_rx;
|
||||||
|
if (led->wl) {
|
||||||
|
b43_led_turn_off(dev, led->index, led->activelow);
|
||||||
|
led->hw_state = 0;
|
||||||
|
atomic_set(&led->state, 0);
|
||||||
|
}
|
||||||
|
led = &dev->wl->leds.led_assoc;
|
||||||
|
if (led->wl) {
|
||||||
|
b43_led_turn_off(dev, led->index, led->activelow);
|
||||||
|
led->hw_state = 0;
|
||||||
|
atomic_set(&led->state, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize other LED states. */
|
||||||
|
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
|
||||||
|
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
|
||||||
|
switch (behaviour) {
|
||||||
|
case B43_LED_OFF:
|
||||||
|
b43_led_turn_off(dev, i, activelow);
|
||||||
|
break;
|
||||||
|
case B43_LED_ON:
|
||||||
|
b43_led_turn_on(dev, i, activelow);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Leave others as-is. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->wl->leds.stop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void b43_leds_exit(struct b43_wldev *dev)
|
void b43_leds_exit(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
b43_unregister_led(&dev->led_tx);
|
struct b43_leds *leds = &dev->wl->leds;
|
||||||
b43_unregister_led(&dev->led_rx);
|
|
||||||
b43_unregister_led(&dev->led_assoc);
|
b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
|
||||||
b43_unregister_led(&dev->led_radio);
|
b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
|
||||||
|
b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
|
||||||
|
b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_leds_stop(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_leds *leds = &dev->wl->leds;
|
||||||
|
|
||||||
|
leds->stop = 1;
|
||||||
|
cancel_work_sync(&leds->work);
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_leds_register(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
enum b43_led_behaviour behaviour;
|
||||||
|
bool activelow;
|
||||||
|
|
||||||
|
INIT_WORK(&dev->wl->leds.work, b43_leds_work);
|
||||||
|
|
||||||
|
/* Register the LEDs to the LED subsystem. */
|
||||||
|
for (i = 0; i < B43_MAX_NR_LEDS; i++) {
|
||||||
|
b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
|
||||||
|
b43_map_led(dev, i, behaviour, activelow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_leds_unregister(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_leds *leds = &dev->wl->leds;
|
||||||
|
|
||||||
|
b43_unregister_led(&leds->led_tx);
|
||||||
|
b43_unregister_led(&leds->led_rx);
|
||||||
|
b43_unregister_led(&leds->led_assoc);
|
||||||
|
b43_unregister_led(&leds->led_radio);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,13 @@ struct b43_wldev;
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
|
||||||
#define B43_LED_MAX_NAME_LEN 31
|
#define B43_LED_MAX_NAME_LEN 31
|
||||||
|
|
||||||
struct b43_led {
|
struct b43_led {
|
||||||
struct b43_wldev *dev;
|
struct b43_wl *wl;
|
||||||
/* The LED class device */
|
/* The LED class device */
|
||||||
struct led_classdev led_dev;
|
struct led_classdev led_dev;
|
||||||
/* The index number of the LED. */
|
/* The index number of the LED. */
|
||||||
|
@ -22,8 +23,24 @@ struct b43_led {
|
||||||
bool activelow;
|
bool activelow;
|
||||||
/* The unique name string for this LED device. */
|
/* The unique name string for this LED device. */
|
||||||
char name[B43_LED_MAX_NAME_LEN + 1];
|
char name[B43_LED_MAX_NAME_LEN + 1];
|
||||||
|
/* The current status of the LED. This is updated locklessly. */
|
||||||
|
atomic_t state;
|
||||||
|
/* The active state in hardware. */
|
||||||
|
bool hw_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct b43_leds {
|
||||||
|
struct b43_led led_tx;
|
||||||
|
struct b43_led led_rx;
|
||||||
|
struct b43_led led_radio;
|
||||||
|
struct b43_led led_assoc;
|
||||||
|
|
||||||
|
bool stop;
|
||||||
|
struct work_struct work;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define B43_MAX_NR_LEDS 4
|
||||||
|
|
||||||
#define B43_LED_BEHAVIOUR 0x7F
|
#define B43_LED_BEHAVIOUR 0x7F
|
||||||
#define B43_LED_ACTIVELOW 0x80
|
#define B43_LED_ACTIVELOW 0x80
|
||||||
/* LED behaviour values */
|
/* LED behaviour values */
|
||||||
|
@ -42,23 +59,35 @@ enum b43_led_behaviour {
|
||||||
B43_LED_INACTIVE,
|
B43_LED_INACTIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void b43_leds_register(struct b43_wldev *dev);
|
||||||
|
void b43_leds_unregister(struct b43_wldev *dev);
|
||||||
void b43_leds_init(struct b43_wldev *dev);
|
void b43_leds_init(struct b43_wldev *dev);
|
||||||
void b43_leds_exit(struct b43_wldev *dev);
|
void b43_leds_exit(struct b43_wldev *dev);
|
||||||
|
void b43_leds_stop(struct b43_wldev *dev);
|
||||||
|
|
||||||
|
|
||||||
#else /* CONFIG_B43_LEDS */
|
#else /* CONFIG_B43_LEDS */
|
||||||
/* LED support disabled */
|
/* LED support disabled */
|
||||||
|
|
||||||
struct b43_led {
|
struct b43_leds {
|
||||||
/* empty */
|
/* empty */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void b43_leds_register(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void b43_leds_unregister(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
static inline void b43_leds_init(struct b43_wldev *dev)
|
static inline void b43_leds_init(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void b43_leds_exit(struct b43_wldev *dev)
|
static inline void b43_leds_exit(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline void b43_leds_stop(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_B43_LEDS */
|
#endif /* CONFIG_B43_LEDS */
|
||||||
|
|
||||||
#endif /* B43_LEDS_H_ */
|
#endif /* B43_LEDS_H_ */
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
|
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
|
||||||
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
|
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
|
||||||
|
|
||||||
|
SDIO support
|
||||||
|
Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
|
||||||
|
|
||||||
Some parts of the code in this file are derived from the ipw2200
|
Some parts of the code in this file are derived from the ipw2200
|
||||||
driver Copyright(c) 2003 - 2004 Intel Corporation.
|
driver Copyright(c) 2003 - 2004 Intel Corporation.
|
||||||
|
|
||||||
|
@ -53,6 +56,8 @@
|
||||||
#include "xmit.h"
|
#include "xmit.h"
|
||||||
#include "lo.h"
|
#include "lo.h"
|
||||||
#include "pcmcia.h"
|
#include "pcmcia.h"
|
||||||
|
#include "sdio.h"
|
||||||
|
#include <linux/mmc/sdio_func.h>
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Broadcom B43 wireless driver");
|
MODULE_DESCRIPTION("Broadcom B43 wireless driver");
|
||||||
MODULE_AUTHOR("Martin Langer");
|
MODULE_AUTHOR("Martin Langer");
|
||||||
|
@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
dev = wl->current_dev;
|
dev = wl->current_dev;
|
||||||
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
|
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
|
||||||
if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
|
if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
|
||||||
/* wl->mutex is enough. */
|
/* wl->mutex is enough. */
|
||||||
b43_do_beacon_update_trigger_work(dev);
|
b43_do_beacon_update_trigger_work(dev);
|
||||||
mmiowb();
|
mmiowb();
|
||||||
|
@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
|
||||||
|
|
||||||
/* Re-enable interrupts on the device by restoring the current interrupt mask. */
|
/* Re-enable interrupts on the device by restoring the current interrupt mask. */
|
||||||
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
|
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
|
||||||
|
|
||||||
|
#if B43_DEBUG
|
||||||
|
if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
|
||||||
|
dev->irq_count++;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
|
||||||
|
if (reason & (1 << i))
|
||||||
|
dev->irq_bit_count[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interrupt thread handler. Handles device interrupts in thread context. */
|
/* Interrupt thread handler. Handles device interrupts in thread context. */
|
||||||
|
@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SDIO interrupt handler. This runs in process context. */
|
||||||
|
static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct b43_wl *wl = dev->wl;
|
||||||
|
irqreturn_t ret;
|
||||||
|
|
||||||
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
|
ret = b43_do_interrupt(dev);
|
||||||
|
if (ret == IRQ_WAKE_THREAD)
|
||||||
|
b43_do_interrupt_thread(dev);
|
||||||
|
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
void b43_do_release_fw(struct b43_firmware_file *fw)
|
void b43_do_release_fw(struct b43_firmware_file *fw)
|
||||||
{
|
{
|
||||||
release_firmware(fw->data);
|
release_firmware(fw->data);
|
||||||
|
@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
|
||||||
cfp_pretbtt = 50;
|
cfp_pretbtt = 50;
|
||||||
}
|
}
|
||||||
b43_write16(dev, 0x612, cfp_pretbtt);
|
b43_write16(dev, 0x612, cfp_pretbtt);
|
||||||
|
|
||||||
|
/* FIXME: We don't currently implement the PMQ mechanism,
|
||||||
|
* so always disable it. If we want to implement PMQ,
|
||||||
|
* we need to enable it here (clear DISCPMQ) in AP mode.
|
||||||
|
*/
|
||||||
|
if (0 /* ctl & B43_MACCTL_AP */) {
|
||||||
|
b43_write32(dev, B43_MMIO_MACCTL,
|
||||||
|
b43_read32(dev, B43_MMIO_MACCTL)
|
||||||
|
& ~B43_MACCTL_DISCPMQ);
|
||||||
|
} else {
|
||||||
|
b43_write32(dev, B43_MMIO_MACCTL,
|
||||||
|
b43_read32(dev, B43_MMIO_MACCTL)
|
||||||
|
| B43_MACCTL_DISCPMQ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
|
static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
|
||||||
|
@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
|
||||||
|
|
||||||
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
|
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
|
#if B43_DEBUG
|
||||||
|
if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n",
|
||||||
|
dev->irq_count / 15,
|
||||||
|
dev->tx_count / 15,
|
||||||
|
dev->rx_count / 15);
|
||||||
|
dev->irq_count = 0;
|
||||||
|
dev->tx_count = 0;
|
||||||
|
dev->rx_count = 0;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
|
||||||
|
if (dev->irq_bit_count[i]) {
|
||||||
|
b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n",
|
||||||
|
dev->irq_bit_count[i] / 15, i, (1 << i));
|
||||||
|
dev->irq_bit_count[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_periodic_work(struct b43_wldev *dev)
|
static void do_periodic_work(struct b43_wldev *dev)
|
||||||
|
@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev)
|
||||||
static int b43_rng_read(struct hwrng *rng, u32 *data)
|
static int b43_rng_read(struct hwrng *rng, u32 *data)
|
||||||
{
|
{
|
||||||
struct b43_wl *wl = (struct b43_wl *)rng->priv;
|
struct b43_wl *wl = (struct b43_wl *)rng->priv;
|
||||||
|
struct b43_wldev *dev;
|
||||||
|
int count = -ENODEV;
|
||||||
|
|
||||||
/* FIXME: We need to take wl->mutex here to make sure the device
|
mutex_lock(&wl->mutex);
|
||||||
* is not going away from under our ass. However it could deadlock
|
dev = wl->current_dev;
|
||||||
* with hwrng internal locking. */
|
if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) {
|
||||||
|
*data = b43_read16(dev, B43_MMIO_RNG);
|
||||||
|
count = sizeof(u16);
|
||||||
|
}
|
||||||
|
mutex_unlock(&wl->mutex);
|
||||||
|
|
||||||
*data = b43_read16(wl->current_dev, B43_MMIO_RNG);
|
return count;
|
||||||
|
|
||||||
return (sizeof(u16));
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_B43_HWRNG */
|
#endif /* CONFIG_B43_HWRNG */
|
||||||
|
|
||||||
|
@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work)
|
||||||
dev_kfree_skb(skb); /* Drop it */
|
dev_kfree_skb(skb); /* Drop it */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if B43_DEBUG
|
||||||
|
dev->tx_count++;
|
||||||
|
#endif
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3820,7 +3892,7 @@ redo:
|
||||||
|
|
||||||
/* Disable interrupts on the device. */
|
/* Disable interrupts on the device. */
|
||||||
b43_set_status(dev, B43_STAT_INITIALIZED);
|
b43_set_status(dev, B43_STAT_INITIALIZED);
|
||||||
if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
|
if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
|
||||||
/* wl->mutex is locked. That is enough. */
|
/* wl->mutex is locked. That is enough. */
|
||||||
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
|
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
|
||||||
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
|
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
|
||||||
|
@ -3830,10 +3902,15 @@ redo:
|
||||||
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
|
b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
|
||||||
spin_unlock_irq(&wl->hardirq_lock);
|
spin_unlock_irq(&wl->hardirq_lock);
|
||||||
}
|
}
|
||||||
/* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */
|
/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
|
||||||
orig_dev = dev;
|
orig_dev = dev;
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
synchronize_irq(dev->dev->irq);
|
if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
|
||||||
|
b43_sdio_free_irq(dev);
|
||||||
|
} else {
|
||||||
|
synchronize_irq(dev->dev->irq);
|
||||||
|
free_irq(dev->dev->irq, dev);
|
||||||
|
}
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
dev = wl->current_dev;
|
dev = wl->current_dev;
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
@ -3850,7 +3927,7 @@ redo:
|
||||||
dev_kfree_skb(skb_dequeue(&wl->tx_queue));
|
dev_kfree_skb(skb_dequeue(&wl->tx_queue));
|
||||||
|
|
||||||
b43_mac_suspend(dev);
|
b43_mac_suspend(dev);
|
||||||
free_irq(dev->dev->irq, dev);
|
b43_leds_exit(dev);
|
||||||
b43dbg(wl, "Wireless interface stopped\n");
|
b43dbg(wl, "Wireless interface stopped\n");
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
|
@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
|
||||||
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
|
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
|
||||||
|
|
||||||
drain_txstatus_queue(dev);
|
drain_txstatus_queue(dev);
|
||||||
err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
|
if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
|
||||||
b43_interrupt_thread_handler,
|
err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
|
||||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
if (err) {
|
||||||
if (err) {
|
b43err(dev->wl, "Cannot request SDIO IRQ\n");
|
||||||
b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
|
goto out;
|
||||||
goto out;
|
}
|
||||||
|
} else {
|
||||||
|
err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
|
||||||
|
b43_interrupt_thread_handler,
|
||||||
|
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||||
|
if (err) {
|
||||||
|
b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are ready to run. */
|
/* We are ready to run. */
|
||||||
|
@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
|
||||||
/* Start maintainance work */
|
/* Start maintainance work */
|
||||||
b43_periodic_tasks_setup(dev);
|
b43_periodic_tasks_setup(dev);
|
||||||
|
|
||||||
|
b43_leds_init(dev);
|
||||||
|
|
||||||
b43dbg(dev->wl, "Wireless interface started\n");
|
b43dbg(dev->wl, "Wireless interface started\n");
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
|
||||||
macctl |= B43_MACCTL_PSM_JMP0;
|
macctl |= B43_MACCTL_PSM_JMP0;
|
||||||
b43_write32(dev, B43_MMIO_MACCTL, macctl);
|
b43_write32(dev, B43_MMIO_MACCTL, macctl);
|
||||||
|
|
||||||
if (!dev->suspend_in_progress) {
|
|
||||||
b43_leds_exit(dev);
|
|
||||||
b43_rng_exit(dev->wl);
|
|
||||||
}
|
|
||||||
b43_dma_free(dev);
|
b43_dma_free(dev);
|
||||||
b43_pio_free(dev);
|
b43_pio_free(dev);
|
||||||
b43_chip_exit(dev);
|
b43_chip_exit(dev);
|
||||||
|
@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
|
||||||
/* Initialize a wireless core */
|
/* Initialize a wireless core */
|
||||||
static int b43_wireless_core_init(struct b43_wldev *dev)
|
static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
struct b43_wl *wl = dev->wl;
|
|
||||||
struct ssb_bus *bus = dev->dev->bus;
|
struct ssb_bus *bus = dev->dev->bus;
|
||||||
struct ssb_sprom *sprom = &bus->sprom;
|
struct ssb_sprom *sprom = &bus->sprom;
|
||||||
struct b43_phy *phy = &dev->phy;
|
struct b43_phy *phy = &dev->phy;
|
||||||
|
@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||||
/* Maximum Contention Window */
|
/* Maximum Contention Window */
|
||||||
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
|
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
|
||||||
|
|
||||||
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
|
if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
|
||||||
|
(dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
|
||||||
|
B43_FORCE_PIO) {
|
||||||
dev->__using_pio_transfers = 1;
|
dev->__using_pio_transfers = 1;
|
||||||
err = b43_pio_init(dev);
|
err = b43_pio_init(dev);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||||
ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
|
ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
|
||||||
b43_upload_card_macaddress(dev);
|
b43_upload_card_macaddress(dev);
|
||||||
b43_security_init(dev);
|
b43_security_init(dev);
|
||||||
if (!dev->suspend_in_progress)
|
|
||||||
b43_rng_init(wl);
|
ieee80211_wake_queues(dev->wl->hw);
|
||||||
|
|
||||||
ieee80211_wake_queues(dev->wl->hw);
|
ieee80211_wake_queues(dev->wl->hw);
|
||||||
|
|
||||||
b43_set_status(dev, B43_STAT_INITIALIZED);
|
b43_set_status(dev, B43_STAT_INITIALIZED);
|
||||||
|
|
||||||
if (!dev->suspend_in_progress)
|
|
||||||
b43_leds_init(dev);
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||||
|
|
||||||
/* Initialize struct b43_wl */
|
/* Initialize struct b43_wl */
|
||||||
wl->hw = hw;
|
wl->hw = hw;
|
||||||
spin_lock_init(&wl->leds_lock);
|
|
||||||
mutex_init(&wl->mutex);
|
mutex_init(&wl->mutex);
|
||||||
spin_lock_init(&wl->hardirq_lock);
|
spin_lock_init(&wl->hardirq_lock);
|
||||||
INIT_LIST_HEAD(&wl->devlist);
|
INIT_LIST_HEAD(&wl->devlist);
|
||||||
|
@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
|
||||||
err = ieee80211_register_hw(wl->hw);
|
err = ieee80211_register_hw(wl->hw);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_one_core_detach;
|
goto err_one_core_detach;
|
||||||
|
b43_leds_register(wl->current_dev);
|
||||||
|
b43_rng_init(wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev)
|
||||||
* might have modified it. Restoring is important, so the networking
|
* might have modified it. Restoring is important, so the networking
|
||||||
* stack can properly free resources. */
|
* stack can properly free resources. */
|
||||||
wl->hw->queues = wl->mac80211_initially_registered_queues;
|
wl->hw->queues = wl->mac80211_initially_registered_queues;
|
||||||
|
b43_leds_stop(wldev);
|
||||||
ieee80211_unregister_hw(wl->hw);
|
ieee80211_unregister_hw(wl->hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
b43_one_core_detach(dev);
|
b43_one_core_detach(dev);
|
||||||
|
|
||||||
if (list_empty(&wl->devlist)) {
|
if (list_empty(&wl->devlist)) {
|
||||||
|
b43_rng_exit(wl);
|
||||||
|
b43_leds_unregister(wldev);
|
||||||
/* Last core on the chip unregistered.
|
/* Last core on the chip unregistered.
|
||||||
* We can destroy common struct b43_wl.
|
* We can destroy common struct b43_wl.
|
||||||
*/
|
*/
|
||||||
|
@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
|
||||||
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
|
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
|
||||||
|
|
||||||
static int b43_suspend(struct ssb_device *dev, pm_message_t state)
|
|
||||||
{
|
|
||||||
struct b43_wldev *wldev = ssb_get_drvdata(dev);
|
|
||||||
struct b43_wl *wl = wldev->wl;
|
|
||||||
|
|
||||||
b43dbg(wl, "Suspending...\n");
|
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
|
||||||
wldev->suspend_in_progress = true;
|
|
||||||
wldev->suspend_init_status = b43_status(wldev);
|
|
||||||
if (wldev->suspend_init_status >= B43_STAT_STARTED)
|
|
||||||
wldev = b43_wireless_core_stop(wldev);
|
|
||||||
if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
|
|
||||||
b43_wireless_core_exit(wldev);
|
|
||||||
mutex_unlock(&wl->mutex);
|
|
||||||
|
|
||||||
b43dbg(wl, "Device suspended.\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int b43_resume(struct ssb_device *dev)
|
|
||||||
{
|
|
||||||
struct b43_wldev *wldev = ssb_get_drvdata(dev);
|
|
||||||
struct b43_wl *wl = wldev->wl;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
b43dbg(wl, "Resuming...\n");
|
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
|
||||||
if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) {
|
|
||||||
err = b43_wireless_core_init(wldev);
|
|
||||||
if (err) {
|
|
||||||
b43err(wl, "Resume failed at core init\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (wldev->suspend_init_status >= B43_STAT_STARTED) {
|
|
||||||
err = b43_wireless_core_start(wldev);
|
|
||||||
if (err) {
|
|
||||||
b43_leds_exit(wldev);
|
|
||||||
b43_rng_exit(wldev->wl);
|
|
||||||
b43_wireless_core_exit(wldev);
|
|
||||||
b43err(wl, "Resume failed at core start\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b43dbg(wl, "Device resumed.\n");
|
|
||||||
out:
|
|
||||||
wldev->suspend_in_progress = false;
|
|
||||||
mutex_unlock(&wl->mutex);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* CONFIG_PM */
|
|
||||||
# define b43_suspend NULL
|
|
||||||
# define b43_resume NULL
|
|
||||||
#endif /* CONFIG_PM */
|
|
||||||
|
|
||||||
static struct ssb_driver b43_ssb_driver = {
|
static struct ssb_driver b43_ssb_driver = {
|
||||||
.name = KBUILD_MODNAME,
|
.name = KBUILD_MODNAME,
|
||||||
.id_table = b43_ssb_tbl,
|
.id_table = b43_ssb_tbl,
|
||||||
.probe = b43_probe,
|
.probe = b43_probe,
|
||||||
.remove = b43_remove,
|
.remove = b43_remove,
|
||||||
.suspend = b43_suspend,
|
|
||||||
.resume = b43_resume,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void b43_print_driverinfo(void)
|
static void b43_print_driverinfo(void)
|
||||||
{
|
{
|
||||||
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
|
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
|
||||||
*feat_leds = "";
|
*feat_leds = "", *feat_sdio = "";
|
||||||
|
|
||||||
#ifdef CONFIG_B43_PCI_AUTOSELECT
|
#ifdef CONFIG_B43_PCI_AUTOSELECT
|
||||||
feat_pci = "P";
|
feat_pci = "P";
|
||||||
|
@ -5015,12 +5038,15 @@ static void b43_print_driverinfo(void)
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_B43_LEDS
|
#ifdef CONFIG_B43_LEDS
|
||||||
feat_leds = "L";
|
feat_leds = "L";
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_B43_SDIO
|
||||||
|
feat_sdio = "S";
|
||||||
#endif
|
#endif
|
||||||
printk(KERN_INFO "Broadcom 43xx driver loaded "
|
printk(KERN_INFO "Broadcom 43xx driver loaded "
|
||||||
"[ Features: %s%s%s%s, Firmware-ID: "
|
"[ Features: %s%s%s%s%s, Firmware-ID: "
|
||||||
B43_SUPPORTED_FIRMWARE_ID " ]\n",
|
B43_SUPPORTED_FIRMWARE_ID " ]\n",
|
||||||
feat_pci, feat_pcmcia, feat_nphy,
|
feat_pci, feat_pcmcia, feat_nphy,
|
||||||
feat_leds);
|
feat_leds, feat_sdio);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init b43_init(void)
|
static int __init b43_init(void)
|
||||||
|
@ -5031,13 +5057,18 @@ static int __init b43_init(void)
|
||||||
err = b43_pcmcia_init();
|
err = b43_pcmcia_init();
|
||||||
if (err)
|
if (err)
|
||||||
goto err_dfs_exit;
|
goto err_dfs_exit;
|
||||||
err = ssb_driver_register(&b43_ssb_driver);
|
err = b43_sdio_init();
|
||||||
if (err)
|
if (err)
|
||||||
goto err_pcmcia_exit;
|
goto err_pcmcia_exit;
|
||||||
|
err = ssb_driver_register(&b43_ssb_driver);
|
||||||
|
if (err)
|
||||||
|
goto err_sdio_exit;
|
||||||
b43_print_driverinfo();
|
b43_print_driverinfo();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err_sdio_exit:
|
||||||
|
b43_sdio_exit();
|
||||||
err_pcmcia_exit:
|
err_pcmcia_exit:
|
||||||
b43_pcmcia_exit();
|
b43_pcmcia_exit();
|
||||||
err_dfs_exit:
|
err_dfs_exit:
|
||||||
|
@ -5048,6 +5079,7 @@ err_dfs_exit:
|
||||||
static void __exit b43_exit(void)
|
static void __exit b43_exit(void)
|
||||||
{
|
{
|
||||||
ssb_driver_unregister(&b43_ssb_driver);
|
ssb_driver_unregister(&b43_ssb_driver);
|
||||||
|
b43_sdio_exit();
|
||||||
b43_pcmcia_exit();
|
b43_pcmcia_exit();
|
||||||
b43_debugfs_exit();
|
b43_debugfs_exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
|
||||||
return B43_TXPWR_RES_DONE;
|
return B43_TXPWR_RES_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
|
||||||
|
} else {
|
||||||
|
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
|
||||||
|
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const struct b43_phy_operations b43_phyops_lp = {
|
const struct b43_phy_operations b43_phyops_lp = {
|
||||||
.allocate = b43_lpphy_op_allocate,
|
.allocate = b43_lpphy_op_allocate,
|
||||||
.free = b43_lpphy_op_free,
|
.free = b43_lpphy_op_free,
|
||||||
|
@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = {
|
||||||
.radio_read = b43_lpphy_op_radio_read,
|
.radio_read = b43_lpphy_op_radio_read,
|
||||||
.radio_write = b43_lpphy_op_radio_write,
|
.radio_write = b43_lpphy_op_radio_write,
|
||||||
.software_rfkill = b43_lpphy_op_software_rfkill,
|
.software_rfkill = b43_lpphy_op_software_rfkill,
|
||||||
.switch_analog = b43_phyop_switch_analog_generic,
|
.switch_analog = b43_lpphy_op_switch_analog,
|
||||||
.switch_channel = b43_lpphy_op_switch_channel,
|
.switch_channel = b43_lpphy_op_switch_channel,
|
||||||
.get_default_chan = b43_lpphy_op_get_default_chan,
|
.get_default_chan = b43_lpphy_op_get_default_chan,
|
||||||
.set_rx_antenna = b43_lpphy_op_set_rx_antenna,
|
.set_rx_antenna = b43_lpphy_op_set_rx_antenna,
|
||||||
|
|
|
@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
||||||
q->buffer_used -= total_len;
|
q->buffer_used -= total_len;
|
||||||
q->free_packet_slots += 1;
|
q->free_packet_slots += 1;
|
||||||
|
|
||||||
ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb);
|
ieee80211_tx_status(dev->wl->hw, pack->skb);
|
||||||
pack->skb = NULL;
|
pack->skb = NULL;
|
||||||
list_add(&pack->list, &q->packets_list);
|
list_add(&pack->list, &q->packets_list);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
/* Returns TRUE, if the radio is enabled in hardware. */
|
/* Returns TRUE, if the radio is enabled in hardware. */
|
||||||
bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
if (dev->phy.rev >= 3) {
|
if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) {
|
||||||
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
|
if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
|
||||||
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
|
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
202
drivers/net/wireless/b43/sdio.c
Normal file
202
drivers/net/wireless/b43/sdio.c
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* Broadcom B43 wireless driver
|
||||||
|
*
|
||||||
|
* SDIO over Sonics Silicon Backplane bus glue for b43.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Albert Herranz
|
||||||
|
* Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mmc/card.h>
|
||||||
|
#include <linux/mmc/sdio_func.h>
|
||||||
|
#include <linux/mmc/sdio_ids.h>
|
||||||
|
#include <linux/ssb/ssb.h>
|
||||||
|
|
||||||
|
#include "sdio.h"
|
||||||
|
#include "b43.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HNBU_CHIPID 0x01 /* vendor & device id */
|
||||||
|
|
||||||
|
#define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */
|
||||||
|
|
||||||
|
|
||||||
|
static const struct b43_sdio_quirk {
|
||||||
|
u16 vendor;
|
||||||
|
u16 device;
|
||||||
|
unsigned int quirks;
|
||||||
|
} b43_sdio_quirks[] = {
|
||||||
|
{ 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
|
||||||
|
{
|
||||||
|
const struct b43_sdio_quirk *q;
|
||||||
|
|
||||||
|
for (q = b43_sdio_quirks; q->quirks; q++) {
|
||||||
|
if (vendor == q->vendor && device == q->device)
|
||||||
|
return q->quirks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
|
||||||
|
{
|
||||||
|
struct b43_sdio *sdio = sdio_get_drvdata(func);
|
||||||
|
struct b43_wldev *dev = sdio->irq_handler_opaque;
|
||||||
|
|
||||||
|
if (unlikely(b43_status(dev) < B43_STAT_STARTED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sdio_release_host(func);
|
||||||
|
sdio->irq_handler(dev);
|
||||||
|
sdio_claim_host(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
int b43_sdio_request_irq(struct b43_wldev *dev,
|
||||||
|
void (*handler)(struct b43_wldev *dev))
|
||||||
|
{
|
||||||
|
struct ssb_bus *bus = dev->dev->bus;
|
||||||
|
struct sdio_func *func = bus->host_sdio;
|
||||||
|
struct b43_sdio *sdio = sdio_get_drvdata(func);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
sdio->irq_handler_opaque = dev;
|
||||||
|
sdio->irq_handler = handler;
|
||||||
|
sdio_claim_host(func);
|
||||||
|
err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
|
||||||
|
sdio_release_host(func);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_sdio_free_irq(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
struct ssb_bus *bus = dev->dev->bus;
|
||||||
|
struct sdio_func *func = bus->host_sdio;
|
||||||
|
struct b43_sdio *sdio = sdio_get_drvdata(func);
|
||||||
|
|
||||||
|
sdio_claim_host(func);
|
||||||
|
sdio_release_irq(func);
|
||||||
|
sdio_release_host(func);
|
||||||
|
sdio->irq_handler_opaque = NULL;
|
||||||
|
sdio->irq_handler = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int b43_sdio_probe(struct sdio_func *func,
|
||||||
|
const struct sdio_device_id *id)
|
||||||
|
{
|
||||||
|
struct b43_sdio *sdio;
|
||||||
|
struct sdio_func_tuple *tuple;
|
||||||
|
u16 vendor = 0, device = 0;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
/* Look for the card chip identifier. */
|
||||||
|
tuple = func->tuples;
|
||||||
|
while (tuple) {
|
||||||
|
switch (tuple->code) {
|
||||||
|
case 0x80:
|
||||||
|
switch (tuple->data[0]) {
|
||||||
|
case HNBU_CHIPID:
|
||||||
|
if (tuple->size != 5)
|
||||||
|
break;
|
||||||
|
vendor = tuple->data[1] | (tuple->data[2]<<8);
|
||||||
|
device = tuple->data[3] | (tuple->data[4]<<8);
|
||||||
|
dev_info(&func->dev, "Chip ID %04x:%04x\n",
|
||||||
|
vendor, device);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tuple = tuple->next;
|
||||||
|
}
|
||||||
|
if (!vendor || !device) {
|
||||||
|
error = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdio_claim_host(func);
|
||||||
|
error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
|
||||||
|
if (error) {
|
||||||
|
dev_err(&func->dev, "failed to set block size to %u bytes,"
|
||||||
|
" error %d\n", B43_SDIO_BLOCK_SIZE, error);
|
||||||
|
goto err_release_host;
|
||||||
|
}
|
||||||
|
error = sdio_enable_func(func);
|
||||||
|
if (error) {
|
||||||
|
dev_err(&func->dev, "failed to enable func, error %d\n", error);
|
||||||
|
goto err_release_host;
|
||||||
|
}
|
||||||
|
sdio_release_host(func);
|
||||||
|
|
||||||
|
sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
|
||||||
|
if (!sdio) {
|
||||||
|
error = -ENOMEM;
|
||||||
|
dev_err(&func->dev, "failed to allocate ssb bus\n");
|
||||||
|
goto err_disable_func;
|
||||||
|
}
|
||||||
|
error = ssb_bus_sdiobus_register(&sdio->ssb, func,
|
||||||
|
b43_sdio_get_quirks(vendor, device));
|
||||||
|
if (error) {
|
||||||
|
dev_err(&func->dev, "failed to register ssb sdio bus,"
|
||||||
|
" error %d\n", error);
|
||||||
|
goto err_free_ssb;
|
||||||
|
}
|
||||||
|
sdio_set_drvdata(func, sdio);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_free_ssb:
|
||||||
|
kfree(sdio);
|
||||||
|
err_disable_func:
|
||||||
|
sdio_disable_func(func);
|
||||||
|
err_release_host:
|
||||||
|
sdio_release_host(func);
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void b43_sdio_remove(struct sdio_func *func)
|
||||||
|
{
|
||||||
|
struct b43_sdio *sdio = sdio_get_drvdata(func);
|
||||||
|
|
||||||
|
ssb_bus_unregister(&sdio->ssb);
|
||||||
|
sdio_disable_func(func);
|
||||||
|
kfree(sdio);
|
||||||
|
sdio_set_drvdata(func, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sdio_device_id b43_sdio_ids[] = {
|
||||||
|
{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sdio_driver b43_sdio_driver = {
|
||||||
|
.name = "b43-sdio",
|
||||||
|
.id_table = b43_sdio_ids,
|
||||||
|
.probe = b43_sdio_probe,
|
||||||
|
.remove = b43_sdio_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
int b43_sdio_init(void)
|
||||||
|
{
|
||||||
|
return sdio_register_driver(&b43_sdio_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void b43_sdio_exit(void)
|
||||||
|
{
|
||||||
|
sdio_unregister_driver(&b43_sdio_driver);
|
||||||
|
}
|
45
drivers/net/wireless/b43/sdio.h
Normal file
45
drivers/net/wireless/b43/sdio.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef B43_SDIO_H_
|
||||||
|
#define B43_SDIO_H_
|
||||||
|
|
||||||
|
#include <linux/ssb/ssb.h>
|
||||||
|
|
||||||
|
struct b43_wldev;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_B43_SDIO
|
||||||
|
|
||||||
|
struct b43_sdio {
|
||||||
|
struct ssb_bus ssb;
|
||||||
|
void *irq_handler_opaque;
|
||||||
|
void (*irq_handler)(struct b43_wldev *dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
int b43_sdio_request_irq(struct b43_wldev *dev,
|
||||||
|
void (*handler)(struct b43_wldev *dev));
|
||||||
|
void b43_sdio_free_irq(struct b43_wldev *dev);
|
||||||
|
|
||||||
|
int b43_sdio_init(void);
|
||||||
|
void b43_sdio_exit(void);
|
||||||
|
|
||||||
|
|
||||||
|
#else /* CONFIG_B43_SDIO */
|
||||||
|
|
||||||
|
|
||||||
|
int b43_sdio_request_irq(struct b43_wldev *dev,
|
||||||
|
void (*handler)(struct b43_wldev *dev))
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
void b43_sdio_free_irq(struct b43_wldev *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline int b43_sdio_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void b43_sdio_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_B43_SDIO */
|
||||||
|
#endif /* B43_SDIO_H_ */
|
|
@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||||
ieee80211_rx_irqsafe(dev->wl->hw, skb);
|
ieee80211_rx(dev->wl->hw, skb);
|
||||||
|
|
||||||
|
#if B43_DEBUG
|
||||||
|
dev->rx_count++;
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
drop:
|
drop:
|
||||||
b43dbg(dev->wl, "RX: Packet dropped\n");
|
b43dbg(dev->wl, "RX: Packet dropped\n");
|
||||||
|
|
|
@ -2021,6 +2021,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
||||||
agg->frame_count, txq_id, idx);
|
agg->frame_count, txq_id, idx);
|
||||||
|
|
||||||
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
|
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
|
||||||
|
if (!hdr) {
|
||||||
|
IWL_ERR(priv,
|
||||||
|
"BUG_ON idx doesn't point to valid skb"
|
||||||
|
" idx=%d, txq_id=%d\n", idx, txq_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||||
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
|
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
|
||||||
|
|
|
@ -1163,6 +1163,12 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
|
||||||
agg->frame_count, txq_id, idx);
|
agg->frame_count, txq_id, idx);
|
||||||
|
|
||||||
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
|
hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
|
||||||
|
if (!hdr) {
|
||||||
|
IWL_ERR(priv,
|
||||||
|
"BUG_ON idx doesn't point to valid skb"
|
||||||
|
" idx=%d, txq_id=%d\n", idx, txq_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||||
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
|
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
|
||||||
|
|
|
@ -250,12 +250,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||||
|
|
||||||
|
if (rxq->free_count > RX_LOW_WATERMARK)
|
||||||
|
priority |= __GFP_NOWARN;
|
||||||
/* Alloc a new receive buffer */
|
/* Alloc a new receive buffer */
|
||||||
skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
|
skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
|
||||||
priority);
|
priority);
|
||||||
|
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
IWL_CRIT(priv, "Can not allocate SKB buffers\n");
|
if (net_ratelimit())
|
||||||
|
IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
|
||||||
|
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
|
||||||
|
net_ratelimit())
|
||||||
|
IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
|
||||||
|
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
|
||||||
|
rxq->free_count);
|
||||||
/* We don't reschedule replenish work here -- we will
|
/* We don't reschedule replenish work here -- we will
|
||||||
* call the restock method and if it still needs
|
* call the restock method and if it still needs
|
||||||
* more buffers it will schedule replenish */
|
* more buffers it will schedule replenish */
|
||||||
|
|
|
@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
|
||||||
struct iwl_host_cmd cmd = {
|
struct iwl_host_cmd cmd = {
|
||||||
.id = REPLY_WEPKEY,
|
.id = REPLY_WEPKEY,
|
||||||
.data = wep_cmd,
|
.data = wep_cmd,
|
||||||
.flags = CMD_SYNC,
|
.flags = CMD_ASYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
memset(wep_cmd, 0, cmd_size +
|
memset(wep_cmd, 0, cmd_size +
|
||||||
|
|
|
@ -1146,11 +1146,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||||
|
|
||||||
|
if (rxq->free_count > RX_LOW_WATERMARK)
|
||||||
|
priority |= __GFP_NOWARN;
|
||||||
/* Alloc a new receive buffer */
|
/* Alloc a new receive buffer */
|
||||||
skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
|
skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
|
IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
|
||||||
|
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
|
||||||
|
net_ratelimit())
|
||||||
|
IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
|
||||||
|
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
|
||||||
|
rxq->free_count);
|
||||||
/* We don't reschedule replenish work here -- we will
|
/* We don't reschedule replenish work here -- we will
|
||||||
* call the restock method and if it still needs
|
* call the restock method and if it still needs
|
||||||
* more buffers it will schedule replenish */
|
* more buffers it will schedule replenish */
|
||||||
|
|
|
@ -380,7 +380,7 @@ static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
|
static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
|
||||||
unsigned int header_length,
|
unsigned int header_length,
|
||||||
struct rxdone_entry_desc *rxdesc)
|
struct rxdone_entry_desc *rxdesc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
menuconfig WL12XX
|
menuconfig WL12XX
|
||||||
boolean "TI wl12xx driver support"
|
tristate "TI wl12xx driver support"
|
||||||
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
|
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
|
||||||
---help---
|
---help---
|
||||||
This will enable TI wl12xx driver support. The drivers make
|
This will enable TI wl12xx driver support. The drivers make
|
||||||
|
|
|
@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf)
|
||||||
|
|
||||||
/* Find bulk out endpoint */
|
/* Find bulk out endpoint */
|
||||||
endpoint = &iface_desc->endpoint[1].desc;
|
endpoint = &iface_desc->endpoint[1].desc;
|
||||||
if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
|
if (usb_endpoint_dir_out(endpoint) &&
|
||||||
usb_endpoint_xfer_bulk(endpoint)) {
|
usb_endpoint_xfer_bulk(endpoint)) {
|
||||||
bulk_out_ep = endpoint->bEndpointAddress;
|
bulk_out_ep = endpoint->bEndpointAddress;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -134,18 +134,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the Rx interrupts for the first buffer */
|
/* Enable the Rx interrupts for the first buffer */
|
||||||
reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
|
|
||||||
out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
|
out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
|
||||||
reg_data | XEL_RSR_RECV_IE_MASK);
|
XEL_RSR_RECV_IE_MASK);
|
||||||
|
|
||||||
/* Enable the Rx interrupts for the second Buffer if
|
/* Enable the Rx interrupts for the second Buffer if
|
||||||
* configured in HW */
|
* configured in HW */
|
||||||
if (drvdata->rx_ping_pong != 0) {
|
if (drvdata->rx_ping_pong != 0) {
|
||||||
reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
|
|
||||||
XEL_RSR_OFFSET);
|
|
||||||
out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
|
out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
|
||||||
XEL_RSR_OFFSET,
|
XEL_RSR_OFFSET,
|
||||||
reg_data | XEL_RSR_RECV_IE_MASK);
|
XEL_RSR_RECV_IE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the Global Interrupt Enable */
|
/* Enable the Global Interrupt Enable */
|
||||||
|
|
|
@ -117,8 +117,6 @@ source "drivers/staging/vt6655/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/vt6656/Kconfig"
|
source "drivers/staging/vt6656/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/cpc-usb/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/staging/udlfb/Kconfig"
|
source "drivers/staging/udlfb/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/hv/Kconfig"
|
source "drivers/staging/hv/Kconfig"
|
||||||
|
|
|
@ -40,7 +40,6 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
|
||||||
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
||||||
obj-$(CONFIG_VT6655) += vt6655/
|
obj-$(CONFIG_VT6655) += vt6655/
|
||||||
obj-$(CONFIG_VT6656) += vt6656/
|
obj-$(CONFIG_VT6656) += vt6656/
|
||||||
obj-$(CONFIG_USB_CPC) += cpc-usb/
|
|
||||||
obj-$(CONFIG_FB_UDL) += udlfb/
|
obj-$(CONFIG_FB_UDL) += udlfb/
|
||||||
obj-$(CONFIG_HYPERV) += hv/
|
obj-$(CONFIG_HYPERV) += hv/
|
||||||
obj-$(CONFIG_VME_BUS) += vme/
|
obj-$(CONFIG_VME_BUS) += vme/
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
config USB_CPC
|
|
||||||
tristate "CPC CAN USB driver"
|
|
||||||
depends on USB && PROC_FS
|
|
||||||
default n
|
|
|
@ -1,3 +0,0 @@
|
||||||
obj-$(CONFIG_USB_CPC) += cpc-usb.o
|
|
||||||
|
|
||||||
cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o
|
|
|
@ -1,10 +0,0 @@
|
||||||
Things to do for this driver to get merged into the main portion of the
|
|
||||||
kernel:
|
|
||||||
- checkpatch cleanups
|
|
||||||
- sparse clean
|
|
||||||
- remove proc code
|
|
||||||
- tie into CAN socket interfaces if possible
|
|
||||||
- figure out sane userspace api
|
|
||||||
- use linux's error codes
|
|
||||||
|
|
||||||
Send patches to Greg Kroah-Hartman <greg@kroah.com>
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,417 +0,0 @@
|
||||||
/*
|
|
||||||
* CPC CAN Interface Definitions
|
|
||||||
*
|
|
||||||
* Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*/
|
|
||||||
#ifndef CPC_HEADER
|
|
||||||
#define CPC_HEADER
|
|
||||||
|
|
||||||
/*
|
|
||||||
* the maximum length of the union members within a CPC_MSG
|
|
||||||
* this value can be defined by the customer, but has to be
|
|
||||||
* >= 64 bytes
|
|
||||||
* however, if not defined before, we set a length of 64 byte
|
|
||||||
*/
|
|
||||||
#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
|
|
||||||
#undef CPC_MSG_LEN
|
|
||||||
#define CPC_MSG_LEN 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transmission of events from CPC interfaces to PC can be individually
|
|
||||||
* controlled per event type. Default state is: don't transmit
|
|
||||||
* Control values are constructed by bit-or of Subject and Action
|
|
||||||
* and passed to CPC_Control()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Control-Values for CPC_Control() Command Subject Selection */
|
|
||||||
#define CONTR_CAN_Message 0x04
|
|
||||||
#define CONTR_Busload 0x08
|
|
||||||
#define CONTR_CAN_State 0x0C
|
|
||||||
#define CONTR_SendAck 0x10
|
|
||||||
#define CONTR_Filter 0x14
|
|
||||||
#define CONTR_CmdQueue 0x18 /* reserved, do not use */
|
|
||||||
#define CONTR_BusError 0x1C
|
|
||||||
|
|
||||||
/* Control Command Actions */
|
|
||||||
#define CONTR_CONT_OFF 0
|
|
||||||
#define CONTR_CONT_ON 1
|
|
||||||
#define CONTR_SING_ON 2
|
|
||||||
/*
|
|
||||||
* CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
|
|
||||||
* read as: transmit at least once
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* defines for confirmed request */
|
|
||||||
#define DO_NOT_CONFIRM 0
|
|
||||||
#define DO_CONFIRM 1
|
|
||||||
|
|
||||||
/* event flags */
|
|
||||||
#define EVENT_READ 0x01
|
|
||||||
#define EVENT_WRITE 0x02
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Messages from CPC to PC contain a message object type field.
|
|
||||||
* The following message types are sent by CPC and can be used in
|
|
||||||
* handlers, others should be ignored.
|
|
||||||
*/
|
|
||||||
#define CPC_MSG_T_RESYNC 0 /* Normally to be ignored */
|
|
||||||
#define CPC_MSG_T_CAN 1 /* CAN data frame */
|
|
||||||
#define CPC_MSG_T_BUSLOAD 2 /* Busload message */
|
|
||||||
#define CPC_MSG_T_STRING 3 /* Normally to be ignored */
|
|
||||||
#define CPC_MSG_T_CONTI 4 /* Normally to be ignored */
|
|
||||||
#define CPC_MSG_T_MEM 7 /* Normally not to be handled */
|
|
||||||
#define CPC_MSG_T_RTR 8 /* CAN remote frame */
|
|
||||||
#define CPC_MSG_T_TXACK 9 /* Send acknowledge */
|
|
||||||
#define CPC_MSG_T_POWERUP 10 /* Power-up message */
|
|
||||||
#define CPC_MSG_T_CMD_NO 11 /* Normally to be ignored */
|
|
||||||
#define CPC_MSG_T_CAN_PRMS 12 /* Actual CAN parameters */
|
|
||||||
#define CPC_MSG_T_ABORTED 13 /* Command aborted message */
|
|
||||||
#define CPC_MSG_T_CANSTATE 14 /* CAN state message */
|
|
||||||
#define CPC_MSG_T_RESET 15 /* used to reset CAN-Controller */
|
|
||||||
#define CPC_MSG_T_XCAN 16 /* XCAN data frame */
|
|
||||||
#define CPC_MSG_T_XRTR 17 /* XCAN remote frame */
|
|
||||||
#define CPC_MSG_T_INFO 18 /* information strings */
|
|
||||||
#define CPC_MSG_T_CONTROL 19 /* used for control of interface/driver behaviour */
|
|
||||||
#define CPC_MSG_T_CONFIRM 20 /* response type for confirmed requests */
|
|
||||||
#define CPC_MSG_T_OVERRUN 21 /* response type for overrun conditions */
|
|
||||||
#define CPC_MSG_T_KEEPALIVE 22 /* response type for keep alive conditions */
|
|
||||||
#define CPC_MSG_T_CANERROR 23 /* response type for bus error conditions */
|
|
||||||
#define CPC_MSG_T_DISCONNECTED 24 /* response type for a disconnected interface */
|
|
||||||
#define CPC_MSG_T_ERR_COUNTER 25 /* RX/TX error counter of CAN controller */
|
|
||||||
|
|
||||||
#define CPC_MSG_T_FIRMWARE 100 /* response type for USB firmware download */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Messages from the PC to the CPC interface contain a command field
|
|
||||||
* Most of the command types are wrapped by the library functions and have therefore
|
|
||||||
* normally not to be used.
|
|
||||||
* However, programmers who wish to circumvent the library and talk directly
|
|
||||||
* to the drivers (mainly Linux programmers) can use the following
|
|
||||||
* command types:
|
|
||||||
*/
|
|
||||||
#define CPC_CMD_T_CAN 1 /* CAN data frame */
|
|
||||||
#define CPC_CMD_T_CONTROL 3 /* used for control of interface/driver behaviour */
|
|
||||||
#define CPC_CMD_T_CAN_PRMS 6 /* set CAN parameters */
|
|
||||||
#define CPC_CMD_T_CLEARBUF 8 /* clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead */
|
|
||||||
#define CPC_CMD_T_INQ_CAN_PARMS 11 /* inquire actual CAN parameters */
|
|
||||||
#define CPC_CMD_T_FILTER_PRMS 12 /* set filter parameter */
|
|
||||||
#define CPC_CMD_T_RTR 13 /* CAN remote frame */
|
|
||||||
#define CPC_CMD_T_CANSTATE 14 /* CAN state message */
|
|
||||||
#define CPC_CMD_T_XCAN 15 /* XCAN data frame */
|
|
||||||
#define CPC_CMD_T_XRTR 16 /* XCAN remote frame */
|
|
||||||
#define CPC_CMD_T_RESET 17 /* used to reset CAN-Controller */
|
|
||||||
#define CPC_CMD_T_INQ_INFO 18 /* miscellanous information strings */
|
|
||||||
#define CPC_CMD_T_OPEN_CHAN 19 /* open a channel */
|
|
||||||
#define CPC_CMD_T_CLOSE_CHAN 20 /* close a channel */
|
|
||||||
#define CPC_CMD_T_CNTBUF 21 /* this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead */
|
|
||||||
#define CPC_CMD_T_CAN_EXIT 200 /* exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1) */
|
|
||||||
|
|
||||||
#define CPC_CMD_T_INQ_MSG_QUEUE_CNT CPC_CMD_T_CNTBUF /* inquires the count of elements in the message queue */
|
|
||||||
#define CPC_CMD_T_INQ_ERR_COUNTER 25 /* request the CAN controllers error counter */
|
|
||||||
#define CPC_CMD_T_CLEAR_MSG_QUEUE CPC_CMD_T_CLEARBUF /* clear CPC_MSG queue */
|
|
||||||
#define CPC_CMD_T_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
|
|
||||||
#define CPC_CMD_T_FIRMWARE 100 /* reserved, must not be used */
|
|
||||||
#define CPC_CMD_T_USB_RESET 101 /* reserved, must not be used */
|
|
||||||
#define CPC_CMD_T_WAIT_NOTIFY 102 /* reserved, must not be used */
|
|
||||||
#define CPC_CMD_T_WAIT_SETUP 103 /* reserved, must not be used */
|
|
||||||
#define CPC_CMD_T_ABORT 255 /* Normally not to be used */
|
|
||||||
|
|
||||||
/* definitions for CPC_MSG_T_INFO information sources */
|
|
||||||
#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
|
|
||||||
#define CPC_INFOMSG_T_INTERFACE 1
|
|
||||||
#define CPC_INFOMSG_T_DRIVER 2
|
|
||||||
#define CPC_INFOMSG_T_LIBRARY 3
|
|
||||||
|
|
||||||
/* information types */
|
|
||||||
#define CPC_INFOMSG_T_UNKNOWN_TYPE 0
|
|
||||||
#define CPC_INFOMSG_T_VERSION 1
|
|
||||||
#define CPC_INFOMSG_T_SERIAL 2
|
|
||||||
|
|
||||||
/* definitions for controller types */
|
|
||||||
#define PCA82C200 1 /* Philips basic CAN controller, replaced by SJA1000 */
|
|
||||||
#define SJA1000 2 /* Philips basic CAN controller */
|
|
||||||
#define AN82527 3 /* Intel full CAN controller */
|
|
||||||
#define M16C_BASIC 4 /* M16C controller running in basic CAN (not full CAN) mode */
|
|
||||||
|
|
||||||
/* channel open error codes */
|
|
||||||
#define CPC_ERR_NO_FREE_CHANNEL -1 /* no more free space within the channel array */
|
|
||||||
#define CPC_ERR_CHANNEL_ALREADY_OPEN -2 /* the channel is already open */
|
|
||||||
#define CPC_ERR_CHANNEL_NOT_ACTIVE -3 /* access to a channel not active failed */
|
|
||||||
#define CPC_ERR_NO_DRIVER_PRESENT -4 /* no driver at the location searched by the library */
|
|
||||||
#define CPC_ERR_NO_INIFILE_PRESENT -5 /* the library could not find the inifile */
|
|
||||||
#define CPC_ERR_WRONG_PARAMETERS -6 /* wrong parameters in the inifile */
|
|
||||||
#define CPC_ERR_NO_INTERFACE_PRESENT -7 /* 1. The specified interface is not connected */
|
|
||||||
/* 2. The interface (mostly CPC-USB) was disconnected upon operation */
|
|
||||||
#define CPC_ERR_NO_MATCHING_CHANNEL -8 /* the driver couldn't find a matching channel */
|
|
||||||
#define CPC_ERR_NO_BUFFER_AVAILABLE -9 /* the driver couldn't allocate buffer for messages */
|
|
||||||
#define CPC_ERR_NO_INTERRUPT -10 /* the requested interrupt couldn't be claimed */
|
|
||||||
#define CPC_ERR_NO_MATCHING_INTERFACE -11 /* no interface type related to this channel was found */
|
|
||||||
#define CPC_ERR_NO_RESOURCES -12 /* the requested resources could not be claimed */
|
|
||||||
#define CPC_ERR_SOCKET -13 /* error concerning TCP sockets */
|
|
||||||
|
|
||||||
/* init error codes */
|
|
||||||
#define CPC_ERR_WRONG_CONTROLLER_TYPE -14 /* wrong CAN controller type within initialization */
|
|
||||||
#define CPC_ERR_NO_RESET_MODE -15 /* the controller could not be set into reset mode */
|
|
||||||
#define CPC_ERR_NO_CAN_ACCESS -16 /* the CAN controller could not be accessed */
|
|
||||||
|
|
||||||
/* transmit error codes */
|
|
||||||
#define CPC_ERR_CAN_WRONG_ID -20 /* the provided CAN id is too big */
|
|
||||||
#define CPC_ERR_CAN_WRONG_LENGTH -21 /* the provided CAN length is too long */
|
|
||||||
#define CPC_ERR_CAN_NO_TRANSMIT_BUF -22 /* the transmit buffer was occupied */
|
|
||||||
#define CPC_ERR_CAN_TRANSMIT_TIMEOUT -23 /* The message could not be sent within a */
|
|
||||||
/* specified time */
|
|
||||||
|
|
||||||
/* other error codes */
|
|
||||||
#define CPC_ERR_SERVICE_NOT_SUPPORTED -30 /* the requested service is not supported by the interface */
|
|
||||||
#define CPC_ERR_IO_TRANSFER -31 /* a transmission error down to the driver occurred */
|
|
||||||
#define CPC_ERR_TRANSMISSION_FAILED -32 /* a transmission error down to the interface occurred */
|
|
||||||
#define CPC_ERR_TRANSMISSION_TIMEOUT -33 /* a timeout occurred within transmission to the interface */
|
|
||||||
#define CPC_ERR_OP_SYS_NOT_SUPPORTED -35 /* the operating system is not supported */
|
|
||||||
#define CPC_ERR_UNKNOWN -40 /* an unknown error ocurred (mostly IOCTL errors) */
|
|
||||||
|
|
||||||
#define CPC_ERR_LOADING_DLL -50 /* the library 'cpcwin.dll' could not be loaded */
|
|
||||||
#define CPC_ERR_ASSIGNING_FUNCTION -51 /* the specified function could not be assigned */
|
|
||||||
#define CPC_ERR_DLL_INITIALIZATION -52 /* the DLL was not initialized correctly */
|
|
||||||
#define CPC_ERR_MISSING_LICFILE -55 /* the file containing the licenses does not exist */
|
|
||||||
#define CPC_ERR_MISSING_LICENSE -56 /* a required license was not found */
|
|
||||||
|
|
||||||
/* CAN state bit values. Ignore any bits not listed */
|
|
||||||
#define CPC_CAN_STATE_BUSOFF 0x80
|
|
||||||
#define CPC_CAN_STATE_ERROR 0x40
|
|
||||||
|
|
||||||
/* Mask to help ignore undefined bits */
|
|
||||||
#define CPC_CAN_STATE_MASK 0xc0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CAN-Message representation in a CPC_MS
|
|
||||||
* Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
|
|
||||||
* or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
|
|
||||||
*/
|
|
||||||
typedef struct CPC_CAN_MSG {
|
|
||||||
u32 id;
|
|
||||||
u8 length;
|
|
||||||
u8 msg[8];
|
|
||||||
} CPC_CAN_MSG_T;
|
|
||||||
|
|
||||||
/* representation of the CAN parameters for the PCA82C200 controller */
|
|
||||||
typedef struct CPC_PCA82C200_PARAMS {
|
|
||||||
u8 acc_code; /* Acceptance-code for receive, Standard: 0 */
|
|
||||||
u8 acc_mask; /* Acceptance-mask for receive, Standard: 0xff (everything) */
|
|
||||||
u8 btr0; /* Bus-timing register 0 */
|
|
||||||
u8 btr1; /* Bus-timing register 1 */
|
|
||||||
u8 outp_contr; /* Output-control register */
|
|
||||||
} CPC_PCA82C200_PARAMS_T;
|
|
||||||
|
|
||||||
/* representation of the CAN parameters for the SJA1000 controller */
|
|
||||||
typedef struct CPC_SJA1000_PARAMS {
|
|
||||||
u8 mode; /* enables single or dual acceptance filtering */
|
|
||||||
u8 acc_code0; /* Acceptance-code for receive, Standard: 0 */
|
|
||||||
u8 acc_code1;
|
|
||||||
u8 acc_code2;
|
|
||||||
u8 acc_code3;
|
|
||||||
u8 acc_mask0; /* Acceptance-mask for receive, Standard: 0xff (everything) */
|
|
||||||
u8 acc_mask1;
|
|
||||||
u8 acc_mask2;
|
|
||||||
u8 acc_mask3;
|
|
||||||
u8 btr0; /* Bus-timing register 0 */
|
|
||||||
u8 btr1; /* Bus-timing register 1 */
|
|
||||||
u8 outp_contr; /* Output-control register */
|
|
||||||
} CPC_SJA1000_PARAMS_T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* representation of the CAN parameters for the M16C controller
|
|
||||||
* in basic CAN mode (means no full CAN)
|
|
||||||
*/
|
|
||||||
typedef struct CPC_M16C_BASIC_PARAMS {
|
|
||||||
u8 con0;
|
|
||||||
u8 con1;
|
|
||||||
u8 ctlr0;
|
|
||||||
u8 ctlr1;
|
|
||||||
u8 clk;
|
|
||||||
u8 acc_std_code0;
|
|
||||||
u8 acc_std_code1;
|
|
||||||
u8 acc_ext_code0;
|
|
||||||
u8 acc_ext_code1;
|
|
||||||
u8 acc_ext_code2;
|
|
||||||
u8 acc_ext_code3;
|
|
||||||
u8 acc_std_mask0;
|
|
||||||
u8 acc_std_mask1;
|
|
||||||
u8 acc_ext_mask0;
|
|
||||||
u8 acc_ext_mask1;
|
|
||||||
u8 acc_ext_mask2;
|
|
||||||
u8 acc_ext_mask3;
|
|
||||||
} CPC_M16C_BASIC_PARAMS_T;
|
|
||||||
|
|
||||||
/* CAN params message representation */
|
|
||||||
typedef struct CPC_CAN_PARAMS {
|
|
||||||
u8 cc_type; /* represents the controller type */
|
|
||||||
union {
|
|
||||||
CPC_M16C_BASIC_PARAMS_T m16c_basic;
|
|
||||||
CPC_SJA1000_PARAMS_T sja1000;
|
|
||||||
CPC_PCA82C200_PARAMS_T pca82c200;
|
|
||||||
} cc_params;
|
|
||||||
} CPC_CAN_PARAMS_T;
|
|
||||||
|
|
||||||
/* CHAN init params representation */
|
|
||||||
typedef struct CPC_CHAN_PARAMS {
|
|
||||||
int fd;
|
|
||||||
} CPC_CHAN_PARAMS_T;
|
|
||||||
|
|
||||||
/* CAN init params message representation */
|
|
||||||
typedef struct CPC_INIT_PARAMS {
|
|
||||||
CPC_CHAN_PARAMS_T chanparams;
|
|
||||||
CPC_CAN_PARAMS_T canparams;
|
|
||||||
} CPC_INIT_PARAMS_T;
|
|
||||||
|
|
||||||
/* structure for confirmed message handling */
|
|
||||||
typedef struct CPC_CONFIRM {
|
|
||||||
u8 result; /* error code */
|
|
||||||
} CPC_CONFIRM_T;
|
|
||||||
|
|
||||||
/* structure for information requests */
|
|
||||||
typedef struct CPC_INFO {
|
|
||||||
u8 source; /* interface, driver or library */
|
|
||||||
u8 type; /* version or serial number */
|
|
||||||
char msg[CPC_MSG_LEN - 2]; /* string holding the requested information */
|
|
||||||
} CPC_INFO_T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OVERRUN
|
|
||||||
* In general two types of overrun may occur.
|
|
||||||
* A hardware overrun, where the CAN controller
|
|
||||||
* lost a message, because the interrupt was
|
|
||||||
* not handled before the next messgae comes in.
|
|
||||||
* Or a software overrun, where i.e. a received
|
|
||||||
* message could not be stored in the CPC_MSG
|
|
||||||
* buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* After a software overrun has occurred
|
|
||||||
* we wait until we have CPC_OVR_GAP slots
|
|
||||||
* free in the CPC_MSG buffer.
|
|
||||||
*/
|
|
||||||
#define CPC_OVR_GAP 10
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Two types of software overrun may occur.
|
|
||||||
* A received CAN message or a CAN state event
|
|
||||||
* can cause an overrun.
|
|
||||||
* Note: A CPC_CMD which would normally store
|
|
||||||
* its result immediately in the CPC_MSG
|
|
||||||
* queue may fail, because the message queue is full.
|
|
||||||
* This will not generate an overrun message, but
|
|
||||||
* will halt command execution, until this command
|
|
||||||
* is able to store its message in the message queue.
|
|
||||||
*/
|
|
||||||
#define CPC_OVR_EVENT_CAN 0x01
|
|
||||||
#define CPC_OVR_EVENT_CANSTATE 0x02
|
|
||||||
#define CPC_OVR_EVENT_BUSERROR 0x04
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the CAN controller lost a message
|
|
||||||
* we indicate it with the highest bit
|
|
||||||
* set in the count field.
|
|
||||||
*/
|
|
||||||
#define CPC_OVR_HW 0x80
|
|
||||||
|
|
||||||
/* structure for overrun conditions */
|
|
||||||
typedef struct {
|
|
||||||
u8 event;
|
|
||||||
u8 count;
|
|
||||||
} CPC_OVERRUN_T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CAN errors
|
|
||||||
* Each CAN controller type has different
|
|
||||||
* registers to record errors.
|
|
||||||
* Therefor a structure containing the specific
|
|
||||||
* errors is set up for each controller here
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SJA1000 error structure
|
|
||||||
* see the SJA1000 datasheet for detailed
|
|
||||||
* explanation of the registers
|
|
||||||
*/
|
|
||||||
typedef struct CPC_SJA1000_CAN_ERROR {
|
|
||||||
u8 ecc; /* error capture code register */
|
|
||||||
u8 rxerr; /* RX error counter register */
|
|
||||||
u8 txerr; /* TX error counter register */
|
|
||||||
} CPC_SJA1000_CAN_ERROR_T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* M16C error structure
|
|
||||||
* see the M16C datasheet for detailed
|
|
||||||
* explanation of the registers
|
|
||||||
*/
|
|
||||||
typedef struct CPC_M16C_CAN_ERROR {
|
|
||||||
u8 tbd; /* to be defined */
|
|
||||||
} CPC_M16C_CAN_ERROR_T;
|
|
||||||
|
|
||||||
/* structure for CAN error conditions */
|
|
||||||
#define CPC_CAN_ECODE_ERRFRAME 0x01
|
|
||||||
typedef struct CPC_CAN_ERROR {
|
|
||||||
u8 ecode;
|
|
||||||
struct {
|
|
||||||
u8 cc_type; /* CAN controller type */
|
|
||||||
union {
|
|
||||||
CPC_SJA1000_CAN_ERROR_T sja1000;
|
|
||||||
CPC_M16C_CAN_ERROR_T m16c;
|
|
||||||
} regs;
|
|
||||||
} cc;
|
|
||||||
} CPC_CAN_ERROR_T;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure containing RX/TX error counter.
|
|
||||||
* This structure is used to request the
|
|
||||||
* values of the CAN controllers TX and RX
|
|
||||||
* error counter.
|
|
||||||
*/
|
|
||||||
typedef struct CPC_CAN_ERR_COUNTER {
|
|
||||||
u8 rx;
|
|
||||||
u8 tx;
|
|
||||||
} CPC_CAN_ERR_COUNTER_T;
|
|
||||||
|
|
||||||
/* If this flag is set, transmissions from PC to CPC are protected against loss */
|
|
||||||
#define CPC_SECURE_TO_CPC 0x01
|
|
||||||
|
|
||||||
/* If this flag is set, transmissions from CPC to PC are protected against loss */
|
|
||||||
#define CPC_SECURE_TO_PC 0x02
|
|
||||||
|
|
||||||
/* If this flag is set, the CAN-transmit buffer is checked to be free before sending a message */
|
|
||||||
#define CPC_SECURE_SEND 0x04
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this flag is set, the transmission complete flag is checked
|
|
||||||
* after sending a message
|
|
||||||
* THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
|
|
||||||
*/
|
|
||||||
#define CPC_SECURE_TRANSMIT 0x08
|
|
||||||
|
|
||||||
/* main message type used between library and application */
|
|
||||||
typedef struct CPC_MSG {
|
|
||||||
u8 type; /* type of message */
|
|
||||||
u8 length; /* length of data within union 'msg' */
|
|
||||||
u8 msgid; /* confirmation handle */
|
|
||||||
u32 ts_sec; /* timestamp in seconds */
|
|
||||||
u32 ts_nsec; /* timestamp in nano seconds */
|
|
||||||
union {
|
|
||||||
u8 generic[CPC_MSG_LEN];
|
|
||||||
CPC_CAN_MSG_T canmsg;
|
|
||||||
CPC_CAN_PARAMS_T canparams;
|
|
||||||
CPC_CONFIRM_T confirmation;
|
|
||||||
CPC_INFO_T info;
|
|
||||||
CPC_OVERRUN_T overrun;
|
|
||||||
CPC_CAN_ERROR_T error;
|
|
||||||
CPC_CAN_ERR_COUNTER_T err_counter;
|
|
||||||
u8 busload;
|
|
||||||
u8 canstate;
|
|
||||||
} msg;
|
|
||||||
} CPC_MSG_T;
|
|
||||||
|
|
||||||
#endif /* CPC_HEADER */
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* CPCLIB
|
|
||||||
*
|
|
||||||
* Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef CPC_INT_H
|
|
||||||
#define CPC_INT_H
|
|
||||||
|
|
||||||
#include <linux/wait.h>
|
|
||||||
|
|
||||||
#define CPC_MSG_BUF_CNT 1500
|
|
||||||
|
|
||||||
#define CPC_PROC_DIR "driver/"
|
|
||||||
|
|
||||||
#undef dbg
|
|
||||||
#undef err
|
|
||||||
#undef info
|
|
||||||
|
|
||||||
/* Use our own dbg macro */
|
|
||||||
#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
|
|
||||||
#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
|
|
||||||
#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
|
|
||||||
|
|
||||||
/* Macros help using of our buffers */
|
|
||||||
#define IsBufferFull(x) (!(x)->WnR) && ((x)->iidx == (x)->oidx)
|
|
||||||
#define IsBufferEmpty(x) ((x)->WnR) && ((x)->iidx == (x)->oidx)
|
|
||||||
#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
|
|
||||||
#define ResetBuffer(x) do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
|
|
||||||
|
|
||||||
#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
|
|
||||||
|
|
||||||
typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
|
|
||||||
unsigned char val);
|
|
||||||
typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
|
|
||||||
|
|
||||||
typedef struct CPC_CHAN {
|
|
||||||
void __iomem * canBase; /* base address of SJA1000 */
|
|
||||||
chan_read_byte_t read_byte; /* CAN controller read access routine */
|
|
||||||
chan_write_byte_t write_byte; /* CAN controller write access routine */
|
|
||||||
CPC_MSG_T *buf; /* buffer for CPC msg */
|
|
||||||
unsigned int iidx;
|
|
||||||
unsigned int oidx;
|
|
||||||
unsigned int WnR;
|
|
||||||
unsigned int minor;
|
|
||||||
unsigned int locked;
|
|
||||||
unsigned int irqDisabled;
|
|
||||||
|
|
||||||
unsigned char cpcCtrlCANMessage;
|
|
||||||
unsigned char cpcCtrlCANState;
|
|
||||||
unsigned char cpcCtrlBUSState;
|
|
||||||
|
|
||||||
unsigned char controllerType;
|
|
||||||
|
|
||||||
unsigned long ovrTimeSec;
|
|
||||||
unsigned long ovrTimeNSec;
|
|
||||||
unsigned long ovrLockedBuffer;
|
|
||||||
CPC_OVERRUN_T ovr;
|
|
||||||
|
|
||||||
/* for debugging only */
|
|
||||||
unsigned int handledIrqs;
|
|
||||||
unsigned int lostMessages;
|
|
||||||
|
|
||||||
unsigned int sentStdCan;
|
|
||||||
unsigned int sentExtCan;
|
|
||||||
unsigned int sentStdRtr;
|
|
||||||
unsigned int sentExtRtr;
|
|
||||||
|
|
||||||
unsigned int recvStdCan;
|
|
||||||
unsigned int recvExtCan;
|
|
||||||
unsigned int recvStdRtr;
|
|
||||||
unsigned int recvExtRtr;
|
|
||||||
|
|
||||||
wait_queue_head_t *CPCWait_q;
|
|
||||||
|
|
||||||
void *private;
|
|
||||||
} CPC_CHAN_T;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,86 +0,0 @@
|
||||||
/* Header for CPC-USB Driver ********************
|
|
||||||
* Copyright 1999, 2000, 2001
|
|
||||||
*
|
|
||||||
* Company: EMS Dr. Thomas Wuensche
|
|
||||||
* Sonnenhang 3
|
|
||||||
* 85304 Ilmmuenster
|
|
||||||
* Phone: +49-8441-490260
|
|
||||||
* Fax: +49-8441-81860
|
|
||||||
* email: support@ems-wuensche.com
|
|
||||||
* WWW: www.ems-wuensche.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CPCUSB_H
|
|
||||||
#define CPCUSB_H
|
|
||||||
|
|
||||||
#undef err
|
|
||||||
#undef dbg
|
|
||||||
#undef info
|
|
||||||
|
|
||||||
/* Use our own dbg macro */
|
|
||||||
#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
|
|
||||||
#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
|
|
||||||
#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
|
|
||||||
|
|
||||||
#define CPC_USB_CARD_CNT 4
|
|
||||||
|
|
||||||
typedef struct CPC_USB_READ_URB {
|
|
||||||
unsigned char *buffer; /* the buffer to send data */
|
|
||||||
size_t size; /* the size of the send buffer */
|
|
||||||
struct urb *urb; /* the urb used to send data */
|
|
||||||
} CPC_USB_READ_URB_T;
|
|
||||||
|
|
||||||
typedef struct CPC_USB_WRITE_URB {
|
|
||||||
unsigned char *buffer; /* the buffer to send data */
|
|
||||||
size_t size; /* the size of the send buffer */
|
|
||||||
struct urb *urb; /* the urb used to send data */
|
|
||||||
atomic_t busy; /* true if write urb is busy */
|
|
||||||
struct completion finished; /* wait for the write to finish */
|
|
||||||
} CPC_USB_WRITE_URB_T;
|
|
||||||
|
|
||||||
#define CPC_USB_URB_CNT 10
|
|
||||||
|
|
||||||
typedef struct CPC_USB {
|
|
||||||
struct usb_device *udev; /* save off the usb device pointer */
|
|
||||||
struct usb_interface *interface; /* the interface for this device */
|
|
||||||
unsigned char minor; /* the starting minor number for this device */
|
|
||||||
unsigned char num_ports; /* the number of ports this device has */
|
|
||||||
int num_intr_in; /* number of interrupt in endpoints we have */
|
|
||||||
int num_bulk_in; /* number of bulk in endpoints we have */
|
|
||||||
int num_bulk_out; /* number of bulk out endpoints we have */
|
|
||||||
|
|
||||||
CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
|
|
||||||
|
|
||||||
unsigned char intr_in_buffer[4]; /* interrupt transfer buffer */
|
|
||||||
struct urb *intr_in_urb; /* interrupt transfer urb */
|
|
||||||
|
|
||||||
CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
|
|
||||||
|
|
||||||
int open; /* if the port is open or not */
|
|
||||||
int present; /* if the device is not disconnected */
|
|
||||||
struct semaphore sem; /* locks this structure */
|
|
||||||
|
|
||||||
int free_slots; /* free send slots of CPC-USB */
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
spinlock_t slock;
|
|
||||||
|
|
||||||
char serialNumber[128]; /* serial number */
|
|
||||||
int productId; /* product id to differ between M16C and LPC2119 */
|
|
||||||
CPC_CHAN_T *chan;
|
|
||||||
} CPC_USB_T;
|
|
||||||
|
|
||||||
#define CPCTable CPCUSB_Table
|
|
||||||
|
|
||||||
#define CPC_DRIVER_VERSION "0.724"
|
|
||||||
#define CPC_DRIVER_SERIAL "not applicable"
|
|
||||||
|
|
||||||
#define OBUF_SIZE 255 /* 4096 */
|
|
||||||
|
|
||||||
/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
|
|
||||||
#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
|
|
||||||
#define RD_EXPIRE 12 /* Number of attempts to wait X seconds */
|
|
||||||
|
|
||||||
#define CPC_USB_BASE_MNR 0 /* CPC-USB start at minor 0 */
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef _SJA2M16C_H
|
|
||||||
#define _SJA2M16C_H
|
|
||||||
|
|
||||||
#include "cpc.h"
|
|
||||||
|
|
||||||
#define BAUDRATE_TOLERANCE_PERCENT 1
|
|
||||||
#define SAMPLEPOINT_TOLERANCE_PERCENT 5
|
|
||||||
#define SAMPLEPOINT_UPPER_LIMIT 88
|
|
||||||
|
|
||||||
/* M16C parameters */
|
|
||||||
struct FIELD_C0CONR {
|
|
||||||
unsigned int brp:4;
|
|
||||||
unsigned int sam:1;
|
|
||||||
unsigned int pr:3;
|
|
||||||
unsigned int dummy:8;
|
|
||||||
};
|
|
||||||
struct FIELD_C1CONR {
|
|
||||||
unsigned int ph1:3;
|
|
||||||
unsigned int ph2:3;
|
|
||||||
unsigned int sjw:2;
|
|
||||||
unsigned int dummy:8;
|
|
||||||
};
|
|
||||||
typedef union C0CONR {
|
|
||||||
unsigned char c0con;
|
|
||||||
struct FIELD_C0CONR bc0con;
|
|
||||||
} C0CONR_T;
|
|
||||||
typedef union C1CONR {
|
|
||||||
unsigned char c1con;
|
|
||||||
struct FIELD_C1CONR bc1con;
|
|
||||||
} C1CONR_T;
|
|
||||||
|
|
||||||
#define SJA_TSEG1 ((pParams->btr1 & 0x0f)+1)
|
|
||||||
#define SJA_TSEG2 (((pParams->btr1 & 0x70)>>4)+1)
|
|
||||||
#define SJA_BRP ((pParams->btr0 & 0x3f)+1)
|
|
||||||
#define SJA_SJW ((pParams->btr0 & 0xc0)>>6)
|
|
||||||
#define SJA_SAM ((pParams->btr1 & 0x80)>>7)
|
|
||||||
int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
|
|
||||||
int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
|
|
||||||
int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,452 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
|
|
||||||
*
|
|
||||||
* - All rights reserved -
|
|
||||||
*
|
|
||||||
* This code is provided "as is" without warranty of any kind, either
|
|
||||||
* expressed or implied, including but not limited to the liability
|
|
||||||
* concerning the freedom from material defects, the fitness for parti-
|
|
||||||
* cular purposes or the freedom of proprietary rights of third parties.
|
|
||||||
*
|
|
||||||
*****************************************************************************
|
|
||||||
* Module name.: cpcusb
|
|
||||||
*****************************************************************************
|
|
||||||
* Include file: cpc.h
|
|
||||||
*****************************************************************************
|
|
||||||
* Project.....: Windows Driver Development Kit
|
|
||||||
* Filename....: sja2m16c.cpp
|
|
||||||
* Authors.....: (GU) Gerhard Uttenthaler
|
|
||||||
* (CS) Christian Schoett
|
|
||||||
*****************************************************************************
|
|
||||||
* Short descr.: converts baudrate between SJA1000 and M16C
|
|
||||||
*****************************************************************************
|
|
||||||
* Description.: handles the baudrate conversion from SJA1000 parameters to
|
|
||||||
* M16C parameters
|
|
||||||
*****************************************************************************
|
|
||||||
* Address : EMS Dr. Thomas Wuensche
|
|
||||||
* Sonnenhang 3
|
|
||||||
* D-85304 Ilmmuenster
|
|
||||||
* Tel. : +49-8441-490260
|
|
||||||
* Fax. : +49-8441-81860
|
|
||||||
* email: support@ems-wuensche.com
|
|
||||||
*****************************************************************************
|
|
||||||
* History
|
|
||||||
*****************************************************************************
|
|
||||||
* Version Date Auth Remark
|
|
||||||
*
|
|
||||||
* 01.00 ?? GU - initial release
|
|
||||||
* 01.10 ?????????? CS - adapted to fit into the USB Windows driver
|
|
||||||
* 02.00 18.08.2004 GU - improved the baudrate calculating algorithm
|
|
||||||
* - implemented acceptance filtering
|
|
||||||
* 02.10 10.09.2004 CS - adapted to fit into the USB Windows driver
|
|
||||||
*****************************************************************************
|
|
||||||
* ToDo's
|
|
||||||
*****************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* I N C L U D E S
|
|
||||||
*/
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/vmalloc.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/poll.h>
|
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/completion.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#include <linux/usb.h>
|
|
||||||
|
|
||||||
#include "cpc.h"
|
|
||||||
#include "cpc_int.h"
|
|
||||||
#include "cpcusb.h"
|
|
||||||
|
|
||||||
#include "sja2m16c.h"
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
|
|
||||||
{
|
|
||||||
return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
|
|
||||||
ph1 + 1 + ph2 +
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
|
|
||||||
{
|
|
||||||
return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
|
|
||||||
ph2 + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Function.....: SJA1000_TO_M16C_BASIC_Params
|
|
||||||
*
|
|
||||||
* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
|
|
||||||
* parameters based on the sample point and the error. In
|
|
||||||
* addition it converts the acceptance filter parameters to
|
|
||||||
* suit the M16C parameters
|
|
||||||
*
|
|
||||||
* Parameters...: None
|
|
||||||
*
|
|
||||||
* Return values: None
|
|
||||||
*
|
|
||||||
* Comments.....:
|
|
||||||
*****************************************************************************
|
|
||||||
* History
|
|
||||||
*****************************************************************************
|
|
||||||
* 19.01.2005 CS - modifed the conversion of SJA1000 filter params into
|
|
||||||
* M16C params. Due to compatibility reasons with the
|
|
||||||
* older 82C200 CAN controller the SJA1000
|
|
||||||
****************************************************************************/
|
|
||||||
int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
|
|
||||||
{
|
|
||||||
int sjaBaudrate;
|
|
||||||
int sjaSamplepoint;
|
|
||||||
int *baudrate_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
|
|
||||||
int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
|
|
||||||
int baudrate_error_merk;
|
|
||||||
int clk, brp, pr, ph1, ph2;
|
|
||||||
int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
|
|
||||||
int index;
|
|
||||||
unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
|
|
||||||
unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
|
|
||||||
CPC_MSG_T * out;
|
|
||||||
C0CONR_T c0con;
|
|
||||||
C1CONR_T c1con;
|
|
||||||
int tmpAccCode;
|
|
||||||
int tmpAccMask;
|
|
||||||
|
|
||||||
// we have to convert the parameters into M16C parameters
|
|
||||||
CPC_SJA1000_PARAMS_T * pParams;
|
|
||||||
|
|
||||||
// check if the type is CAN parameters and if we have to convert the given params
|
|
||||||
if (in->type != CPC_CMD_T_CAN_PRMS
|
|
||||||
|| in->msg.canparams.cc_type != SJA1000)
|
|
||||||
return 0;
|
|
||||||
pParams =
|
|
||||||
(CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
|
|
||||||
acc_code0 = pParams->acc_code0;
|
|
||||||
acc_code1 = pParams->acc_code1;
|
|
||||||
acc_code2 = pParams->acc_code2;
|
|
||||||
acc_code3 = pParams->acc_code3;
|
|
||||||
acc_mask0 = pParams->acc_mask0;
|
|
||||||
acc_mask1 = pParams->acc_mask1;
|
|
||||||
acc_mask2 = pParams->acc_mask2;
|
|
||||||
acc_mask3 = pParams->acc_mask3;
|
|
||||||
|
|
||||||
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
|
|
||||||
info("acc_code0: %2.2Xh\n", acc_code0);
|
|
||||||
info("acc_code1: %2.2Xh\n", acc_code1);
|
|
||||||
info("acc_code2: %2.2Xh\n", acc_code2);
|
|
||||||
info("acc_code3: %2.2Xh\n", acc_code3);
|
|
||||||
info("acc_mask0: %2.2Xh\n", acc_mask0);
|
|
||||||
info("acc_mask1: %2.2Xh\n", acc_mask1);
|
|
||||||
info("acc_mask2: %2.2Xh\n", acc_mask2);
|
|
||||||
info("acc_mask3: %2.2Xh\n", acc_mask3);
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
if (!
|
|
||||||
(baudrate_error =
|
|
||||||
(int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
|
|
||||||
err("Could not allocate memory\n");
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
if (!
|
|
||||||
(samplepoint_error =
|
|
||||||
(int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
|
|
||||||
err("Could not allocate memory\n");
|
|
||||||
vfree(baudrate_error);
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
memset(baudrate_error, 0xff, sizeof(baudrate_error));
|
|
||||||
memset(samplepoint_error, 0xff, sizeof(baudrate_error));
|
|
||||||
sjaBaudrate =
|
|
||||||
16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
|
|
||||||
sjaSamplepoint =
|
|
||||||
100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
|
|
||||||
if (sjaBaudrate == 0) {
|
|
||||||
vfree(baudrate_error);
|
|
||||||
vfree(samplepoint_error);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
|
|
||||||
info("\nStarting SJA CAN params\n");
|
|
||||||
info("-------------------------\n");
|
|
||||||
info("TS1 : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
|
|
||||||
info("BTR0 : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
|
|
||||||
pParams->btr1);
|
|
||||||
info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
|
|
||||||
sjaBaudrate % 1000);
|
|
||||||
info("Sample P: 0.%d\n", sjaSamplepoint);
|
|
||||||
info("\n");
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
c0con.bc0con.sam = SJA_SAM;
|
|
||||||
c1con.bc1con.sjw = SJA_SJW;
|
|
||||||
|
|
||||||
// calculate errors for all baudrates
|
|
||||||
index = 0;
|
|
||||||
for (clk = 0; clk < 5; clk++) {
|
|
||||||
for (brp = 0; brp < 16; brp++) {
|
|
||||||
for (pr = 0; pr < 8; pr++) {
|
|
||||||
for (ph1 = 0; ph1 < 8; ph1++) {
|
|
||||||
for (ph2 = 0; ph2 < 8; ph2++) {
|
|
||||||
baudrate_error[index] =
|
|
||||||
100 *
|
|
||||||
abs(baudrate_m16c
|
|
||||||
(clk, brp, pr, ph1,
|
|
||||||
ph2) -
|
|
||||||
sjaBaudrate) /
|
|
||||||
sjaBaudrate;
|
|
||||||
samplepoint_error[index] =
|
|
||||||
abs(samplepoint_m16c
|
|
||||||
(brp, pr, ph1,
|
|
||||||
ph2) -
|
|
||||||
sjaSamplepoint);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
info
|
|
||||||
("Baudrate : %d kBaud\n",
|
|
||||||
baudrate_m16c(clk,
|
|
||||||
brp, pr,
|
|
||||||
ph1,
|
|
||||||
ph2));
|
|
||||||
info
|
|
||||||
("Baudrate Error: %d\n",
|
|
||||||
baudrate_error
|
|
||||||
[index]);
|
|
||||||
info
|
|
||||||
("Sample P Error: %d\n",
|
|
||||||
samplepoint_error
|
|
||||||
[index]);
|
|
||||||
info
|
|
||||||
("clk : %d\n",
|
|
||||||
clk);
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark all baudrate_error entries which are outer limits
|
|
||||||
index = 0;
|
|
||||||
for (clk = 0; clk < 5; clk++) {
|
|
||||||
for (brp = 0; brp < 16; brp++) {
|
|
||||||
for (pr = 0; pr < 8; pr++) {
|
|
||||||
for (ph1 = 0; ph1 < 8; ph1++) {
|
|
||||||
for (ph2 = 0; ph2 < 8; ph2++) {
|
|
||||||
if ((baudrate_error[index]
|
|
||||||
>
|
|
||||||
BAUDRATE_TOLERANCE_PERCENT)
|
|
||||||
||
|
|
||||||
(samplepoint_error
|
|
||||||
[index] >
|
|
||||||
SAMPLEPOINT_TOLERANCE_PERCENT)
|
|
||||||
||
|
|
||||||
(samplepoint_m16c
|
|
||||||
(brp, pr, ph1,
|
|
||||||
ph2) >
|
|
||||||
SAMPLEPOINT_UPPER_LIMIT))
|
|
||||||
{
|
|
||||||
baudrate_error
|
|
||||||
[index] = -1;
|
|
||||||
} else
|
|
||||||
if (((1 + pr + 1 +
|
|
||||||
ph1 + 1 + ph2 +
|
|
||||||
1) < 8)
|
|
||||||
||
|
|
||||||
((1 + pr + 1 +
|
|
||||||
ph1 + 1 + ph2 +
|
|
||||||
1) > 25)) {
|
|
||||||
baudrate_error
|
|
||||||
[index] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
else {
|
|
||||||
info
|
|
||||||
("Baudrate : %d kBaud\n",
|
|
||||||
baudrate_m16c
|
|
||||||
(clk, brp, pr,
|
|
||||||
ph1, ph2));
|
|
||||||
info
|
|
||||||
("Baudrate Error: %d\n",
|
|
||||||
baudrate_error
|
|
||||||
[index]);
|
|
||||||
info
|
|
||||||
("Sample P Error: %d\n",
|
|
||||||
samplepoint_error
|
|
||||||
[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// find list of minimum of baudrate_error within unmarked entries
|
|
||||||
clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
|
|
||||||
baudrate_error_merk = 100;
|
|
||||||
index = 0;
|
|
||||||
for (clk = 0; clk < 5; clk++) {
|
|
||||||
for (brp = 0; brp < 16; brp++) {
|
|
||||||
for (pr = 0; pr < 8; pr++) {
|
|
||||||
for (ph1 = 0; ph1 < 8; ph1++) {
|
|
||||||
for (ph2 = 0; ph2 < 8; ph2++) {
|
|
||||||
if (baudrate_error[index]
|
|
||||||
!= -1) {
|
|
||||||
if (baudrate_error
|
|
||||||
[index] <
|
|
||||||
baudrate_error_merk)
|
|
||||||
{
|
|
||||||
baudrate_error_merk
|
|
||||||
=
|
|
||||||
baudrate_error
|
|
||||||
[index];
|
|
||||||
brp_merk =
|
|
||||||
brp;
|
|
||||||
pr_merk =
|
|
||||||
pr;
|
|
||||||
ph1_merk =
|
|
||||||
ph1;
|
|
||||||
ph2_merk =
|
|
||||||
ph2;
|
|
||||||
clk_merk =
|
|
||||||
clk;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
info
|
|
||||||
("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
|
|
||||||
brp,
|
|
||||||
pr,
|
|
||||||
ph1,
|
|
||||||
ph2);
|
|
||||||
info
|
|
||||||
("Baudrate : %d kBaud\n",
|
|
||||||
baudrate_m16c
|
|
||||||
(clk,
|
|
||||||
brp,
|
|
||||||
pr,
|
|
||||||
ph1,
|
|
||||||
ph2));
|
|
||||||
info
|
|
||||||
("Baudrate Error: %d\n",
|
|
||||||
baudrate_error
|
|
||||||
[index]);
|
|
||||||
info
|
|
||||||
("Sample P Error: %d\n",
|
|
||||||
samplepoint_error
|
|
||||||
[index]);
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (baudrate_error_merk == 100) {
|
|
||||||
info("ERROR: Could not convert CAN init parameter\n");
|
|
||||||
vfree(baudrate_error);
|
|
||||||
vfree(samplepoint_error);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setting m16c CAN parameter
|
|
||||||
c0con.bc0con.brp = brp_merk;
|
|
||||||
c0con.bc0con.pr = pr_merk;
|
|
||||||
c1con.bc1con.ph1 = ph1_merk;
|
|
||||||
c1con.bc1con.ph2 = ph2_merk;
|
|
||||||
|
|
||||||
#ifdef _DEBUG_OUTPUT_CAN_PARAMS
|
|
||||||
info("\nResulting M16C CAN params\n");
|
|
||||||
info("-------------------------\n");
|
|
||||||
info("clk : %2.2Xh\n", clk_merk);
|
|
||||||
info("ph1 : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
|
|
||||||
c1con.bc1con.ph2 + 1);
|
|
||||||
info("pr : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
|
|
||||||
c0con.bc0con.brp + 1);
|
|
||||||
info("sjw : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
|
|
||||||
c0con.bc0con.sam);
|
|
||||||
info("co1 : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
|
|
||||||
info("Baudrate: %d.%dBaud\n",
|
|
||||||
baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
|
|
||||||
c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
|
|
||||||
baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
|
|
||||||
c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
|
|
||||||
info("Sample P: 0.%d\n",
|
|
||||||
samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
|
|
||||||
c1con.bc1con.ph1, c1con.bc1con.ph2));
|
|
||||||
info("\n");
|
|
||||||
|
|
||||||
#endif /* */
|
|
||||||
out = in;
|
|
||||||
out->type = 6;
|
|
||||||
out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
|
|
||||||
out->msg.canparams.cc_type = M16C_BASIC;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
|
|
||||||
acc_code0;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
|
|
||||||
|
|
||||||
// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
|
|
||||||
tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
|
|
||||||
(unsigned char) tmpAccCode;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
|
|
||||||
(unsigned char) (tmpAccCode >> 8);
|
|
||||||
|
|
||||||
// info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
|
|
||||||
~acc_mask0;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
|
|
||||||
~acc_mask1;
|
|
||||||
|
|
||||||
// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
|
|
||||||
tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
|
|
||||||
|
|
||||||
// info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
|
|
||||||
(unsigned char) ~tmpAccMask;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
|
|
||||||
(unsigned char) ~(tmpAccMask >> 8);
|
|
||||||
|
|
||||||
// info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
|
|
||||||
(unsigned char) tmpAccCode;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
|
|
||||||
(unsigned char) (tmpAccCode >> 8);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
|
|
||||||
(unsigned char) ~tmpAccMask;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
|
|
||||||
(unsigned char) ~(tmpAccMask >> 8);
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
|
|
||||||
~acc_mask2;
|
|
||||||
out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
|
|
||||||
~acc_mask3;
|
|
||||||
vfree(baudrate_error);
|
|
||||||
vfree(samplepoint_error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ extern struct sock *netlink_kernel_create(struct net *net,
|
||||||
extern void netlink_kernel_release(struct sock *sk);
|
extern void netlink_kernel_release(struct sock *sk);
|
||||||
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
|
extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
|
||||||
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
|
extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
|
||||||
|
extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
|
||||||
extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
|
extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
|
||||||
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
|
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
|
||||||
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
|
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#define PNPIPE_IFINDEX 2
|
#define PNPIPE_IFINDEX 2
|
||||||
|
|
||||||
#define PNADDR_ANY 0
|
#define PNADDR_ANY 0
|
||||||
|
#define PNADDR_BROADCAST 0xFC
|
||||||
#define PNPORT_RESOURCE_ROUTING 0
|
#define PNPORT_RESOURCE_ROUTING 0
|
||||||
|
|
||||||
/* Values for PNPIPE_ENCAP option */
|
/* Values for PNPIPE_ENCAP option */
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct driver_info {
|
||||||
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
|
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
|
||||||
#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
|
#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
|
||||||
#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
|
#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
|
||||||
|
#define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */
|
||||||
|
|
||||||
|
|
||||||
/* init device ... can sleep, or cause probe() failure */
|
/* init device ... can sleep, or cause probe() failure */
|
||||||
|
|
|
@ -12,7 +12,6 @@ struct ip_tunnel
|
||||||
struct ip_tunnel *next;
|
struct ip_tunnel *next;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
|
||||||
int recursion; /* Depth of hard_start_xmit recursion */
|
|
||||||
int err_count; /* Number of arrived ICMP errors */
|
int err_count; /* Number of arrived ICMP errors */
|
||||||
unsigned long err_time; /* Time when the last ICMP error arrived */
|
unsigned long err_time; /* Time when the last ICMP error arrived */
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ cond_syscall(sys_sendmsg);
|
||||||
cond_syscall(compat_sys_sendmsg);
|
cond_syscall(compat_sys_sendmsg);
|
||||||
cond_syscall(sys_recvmsg);
|
cond_syscall(sys_recvmsg);
|
||||||
cond_syscall(compat_sys_recvmsg);
|
cond_syscall(compat_sys_recvmsg);
|
||||||
|
cond_syscall(compat_sys_recvfrom);
|
||||||
cond_syscall(sys_socketcall);
|
cond_syscall(sys_socketcall);
|
||||||
cond_syscall(sys_futex);
|
cond_syscall(sys_futex);
|
||||||
cond_syscall(compat_sys_futex);
|
cond_syscall(compat_sys_futex);
|
||||||
|
|
|
@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
|
static char *ip6_compressed_string(char *p, const char *addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
|
||||||
u8 hi;
|
u8 hi;
|
||||||
u8 lo;
|
u8 lo;
|
||||||
bool needcolon = false;
|
bool needcolon = false;
|
||||||
bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr);
|
bool useIPv4;
|
||||||
|
struct in6_addr in6;
|
||||||
|
|
||||||
|
memcpy(&in6, addr, sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
|
||||||
|
|
||||||
memset(zerolength, 0, sizeof(zerolength));
|
memset(zerolength, 0, sizeof(zerolength));
|
||||||
|
|
||||||
|
@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
|
||||||
/* find position of longest 0 run */
|
/* find position of longest 0 run */
|
||||||
for (i = 0; i < range; i++) {
|
for (i = 0; i < range; i++) {
|
||||||
for (j = i; j < range; j++) {
|
for (j = i; j < range; j++) {
|
||||||
if (addr->s6_addr16[j] != 0)
|
if (in6.s6_addr16[j] != 0)
|
||||||
break;
|
break;
|
||||||
zerolength[i]++;
|
zerolength[i]++;
|
||||||
}
|
}
|
||||||
|
@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
|
||||||
needcolon = false;
|
needcolon = false;
|
||||||
}
|
}
|
||||||
/* hex u16 without leading 0s */
|
/* hex u16 without leading 0s */
|
||||||
word = ntohs(addr->s6_addr16[i]);
|
word = ntohs(in6.s6_addr16[i]);
|
||||||
hi = word >> 8;
|
hi = word >> 8;
|
||||||
lo = word & 0xff;
|
lo = word & 0xff;
|
||||||
if (hi) {
|
if (hi) {
|
||||||
|
@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
|
||||||
if (useIPv4) {
|
if (useIPv4) {
|
||||||
if (needcolon)
|
if (needcolon)
|
||||||
*p++ = ':';
|
*p++ = ':';
|
||||||
p = ip4_string(p, &addr->s6_addr[12], false);
|
p = ip4_string(p, &in6.s6_addr[12], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt)
|
static char *ip6_string(char *p, const char *addr, const char *fmt)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
p = pack_hex_byte(p, addr->s6_addr[2 * i]);
|
p = pack_hex_byte(p, *addr++);
|
||||||
p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]);
|
p = pack_hex_byte(p, *addr++);
|
||||||
if (fmt[0] == 'I' && i != 7)
|
if (fmt[0] == 'I' && i != 7)
|
||||||
*p++ = ':';
|
*p++ = ':';
|
||||||
}
|
}
|
||||||
|
@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
|
||||||
char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
|
char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
|
||||||
|
|
||||||
if (fmt[0] == 'I' && fmt[2] == 'c')
|
if (fmt[0] == 'I' && fmt[2] == 'c')
|
||||||
ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr);
|
ip6_compressed_string(ip6_addr, addr);
|
||||||
else
|
else
|
||||||
ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt);
|
ip6_string(ip6_addr, addr, fmt);
|
||||||
|
|
||||||
return string(buf, end, ip6_addr, spec);
|
return string(buf, end, ip6_addr, spec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||||
ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
|
ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
|
||||||
ax25_info.n2count = ax25->n2count;
|
ax25_info.n2count = ax25->n2count;
|
||||||
ax25_info.state = ax25->state;
|
ax25_info.state = ax25->state;
|
||||||
ax25_info.rcv_q = sk_wmem_alloc_get(sk);
|
ax25_info.rcv_q = sk_rmem_alloc_get(sk);
|
||||||
ax25_info.snd_q = sk_rmem_alloc_get(sk);
|
ax25_info.snd_q = sk_wmem_alloc_get(sk);
|
||||||
ax25_info.vs = ax25->vs;
|
ax25_info.vs = ax25->vs;
|
||||||
ax25_info.vr = ax25->vr;
|
ax25_info.vr = ax25->vr;
|
||||||
ax25_info.va = ax25->va;
|
ax25_info.va = ax25->va;
|
||||||
|
|
|
@ -192,11 +192,10 @@
|
||||||
#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */
|
#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */
|
||||||
|
|
||||||
/* Thread control flag bits */
|
/* Thread control flag bits */
|
||||||
#define T_TERMINATE (1<<0)
|
#define T_STOP (1<<0) /* Stop run */
|
||||||
#define T_STOP (1<<1) /* Stop run */
|
#define T_RUN (1<<1) /* Start run */
|
||||||
#define T_RUN (1<<2) /* Start run */
|
#define T_REMDEVALL (1<<2) /* Remove all devs */
|
||||||
#define T_REMDEVALL (1<<3) /* Remove all devs */
|
#define T_REMDEV (1<<3) /* Remove one dev */
|
||||||
#define T_REMDEV (1<<4) /* Remove one dev */
|
|
||||||
|
|
||||||
/* If lock -- can be removed after some work */
|
/* If lock -- can be removed after some work */
|
||||||
#define if_lock(t) spin_lock(&(t->if_lock));
|
#define if_lock(t) spin_lock(&(t->if_lock));
|
||||||
|
@ -2105,7 +2104,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
|
||||||
|
|
||||||
static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
|
static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
|
||||||
{
|
{
|
||||||
ktime_t start;
|
ktime_t start_time, end_time;
|
||||||
s32 remaining;
|
s32 remaining;
|
||||||
struct hrtimer_sleeper t;
|
struct hrtimer_sleeper t;
|
||||||
|
|
||||||
|
@ -2116,7 +2115,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
|
||||||
if (remaining <= 0)
|
if (remaining <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
start = ktime_now();
|
start_time = ktime_now();
|
||||||
if (remaining < 100)
|
if (remaining < 100)
|
||||||
udelay(remaining); /* really small just spin */
|
udelay(remaining); /* really small just spin */
|
||||||
else {
|
else {
|
||||||
|
@ -2135,7 +2134,10 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
|
||||||
} while (t.task && pkt_dev->running && !signal_pending(current));
|
} while (t.task && pkt_dev->running && !signal_pending(current));
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
}
|
}
|
||||||
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start));
|
end_time = ktime_now();
|
||||||
|
|
||||||
|
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
|
||||||
|
pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
|
static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
|
||||||
|
@ -3365,18 +3367,28 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
|
||||||
mutex_unlock(&pktgen_thread_lock);
|
mutex_unlock(&pktgen_thread_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idle(struct pktgen_dev *pkt_dev)
|
static void pktgen_resched(struct pktgen_dev *pkt_dev)
|
||||||
{
|
{
|
||||||
ktime_t idle_start = ktime_now();
|
ktime_t idle_start = ktime_now();
|
||||||
|
schedule();
|
||||||
if (need_resched())
|
|
||||||
schedule();
|
|
||||||
else
|
|
||||||
cpu_relax();
|
|
||||||
|
|
||||||
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
|
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
|
||||||
|
{
|
||||||
|
ktime_t idle_start = ktime_now();
|
||||||
|
|
||||||
|
while (atomic_read(&(pkt_dev->skb->users)) != 1) {
|
||||||
|
if (signal_pending(current))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (need_resched())
|
||||||
|
pktgen_resched(pkt_dev);
|
||||||
|
else
|
||||||
|
cpu_relax();
|
||||||
|
}
|
||||||
|
pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
|
||||||
|
}
|
||||||
|
|
||||||
static void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
static void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||||
{
|
{
|
||||||
|
@ -3387,36 +3399,21 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||||
u16 queue_map;
|
u16 queue_map;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (pkt_dev->delay) {
|
/* If device is offline, then don't send */
|
||||||
spin(pkt_dev, pkt_dev->next_tx);
|
if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) {
|
||||||
|
pktgen_stop_device(pkt_dev);
|
||||||
/* This is max DELAY, this has special meaning of
|
|
||||||
* "never transmit"
|
|
||||||
*/
|
|
||||||
if (pkt_dev->delay == ULLONG_MAX) {
|
|
||||||
pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pkt_dev->skb) {
|
|
||||||
set_cur_queue_map(pkt_dev);
|
|
||||||
queue_map = pkt_dev->cur_queue_map;
|
|
||||||
} else {
|
|
||||||
queue_map = skb_get_queue_mapping(pkt_dev->skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
txq = netdev_get_tx_queue(odev, queue_map);
|
|
||||||
/* Did we saturate the queue already? */
|
|
||||||
if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) {
|
|
||||||
/* If device is down, then all queues are permnantly frozen */
|
|
||||||
if (netif_running(odev))
|
|
||||||
idle(pkt_dev);
|
|
||||||
else
|
|
||||||
pktgen_stop_device(pkt_dev);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is max DELAY, this has special meaning of
|
||||||
|
* "never transmit"
|
||||||
|
*/
|
||||||
|
if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
|
||||||
|
pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no skb or clone count exhausted then get new one */
|
||||||
if (!pkt_dev->skb || (pkt_dev->last_ok &&
|
if (!pkt_dev->skb || (pkt_dev->last_ok &&
|
||||||
++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
|
++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
|
||||||
/* build a new pkt */
|
/* build a new pkt */
|
||||||
|
@ -3435,54 +3432,45 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
|
||||||
pkt_dev->clone_count = 0; /* reset counter */
|
pkt_dev->clone_count = 0; /* reset counter */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill_packet() might have changed the queue */
|
if (pkt_dev->delay && pkt_dev->last_ok)
|
||||||
|
spin(pkt_dev, pkt_dev->next_tx);
|
||||||
|
|
||||||
queue_map = skb_get_queue_mapping(pkt_dev->skb);
|
queue_map = skb_get_queue_mapping(pkt_dev->skb);
|
||||||
txq = netdev_get_tx_queue(odev, queue_map);
|
txq = netdev_get_tx_queue(odev, queue_map);
|
||||||
|
|
||||||
__netif_tx_lock_bh(txq);
|
__netif_tx_lock_bh(txq);
|
||||||
|
atomic_inc(&(pkt_dev->skb->users));
|
||||||
|
|
||||||
if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
|
if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
|
||||||
pkt_dev->last_ok = 0;
|
ret = NETDEV_TX_BUSY;
|
||||||
else {
|
else
|
||||||
atomic_inc(&(pkt_dev->skb->users));
|
|
||||||
|
|
||||||
retry_now:
|
|
||||||
ret = (*xmit)(pkt_dev->skb, odev);
|
ret = (*xmit)(pkt_dev->skb, odev);
|
||||||
switch (ret) {
|
|
||||||
case NETDEV_TX_OK:
|
|
||||||
txq_trans_update(txq);
|
|
||||||
pkt_dev->last_ok = 1;
|
|
||||||
pkt_dev->sofar++;
|
|
||||||
pkt_dev->seq_num++;
|
|
||||||
pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
|
|
||||||
break;
|
|
||||||
case NETDEV_TX_LOCKED:
|
|
||||||
cpu_relax();
|
|
||||||
goto retry_now;
|
|
||||||
default: /* Drivers are not supposed to return other values! */
|
|
||||||
if (net_ratelimit())
|
|
||||||
pr_info("pktgen: %s xmit error: %d\n",
|
|
||||||
odev->name, ret);
|
|
||||||
pkt_dev->errors++;
|
|
||||||
/* fallthru */
|
|
||||||
case NETDEV_TX_BUSY:
|
|
||||||
/* Retry it next time */
|
|
||||||
atomic_dec(&(pkt_dev->skb->users));
|
|
||||||
pkt_dev->last_ok = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pkt_dev->delay)
|
switch (ret) {
|
||||||
pkt_dev->next_tx = ktime_add_ns(ktime_now(),
|
case NETDEV_TX_OK:
|
||||||
pkt_dev->delay);
|
txq_trans_update(txq);
|
||||||
|
pkt_dev->last_ok = 1;
|
||||||
|
pkt_dev->sofar++;
|
||||||
|
pkt_dev->seq_num++;
|
||||||
|
pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
|
||||||
|
break;
|
||||||
|
default: /* Drivers are not supposed to return other values! */
|
||||||
|
if (net_ratelimit())
|
||||||
|
pr_info("pktgen: %s xmit error: %d\n",
|
||||||
|
odev->name, ret);
|
||||||
|
pkt_dev->errors++;
|
||||||
|
/* fallthru */
|
||||||
|
case NETDEV_TX_LOCKED:
|
||||||
|
case NETDEV_TX_BUSY:
|
||||||
|
/* Retry it next time */
|
||||||
|
atomic_dec(&(pkt_dev->skb->users));
|
||||||
|
pkt_dev->last_ok = 0;
|
||||||
}
|
}
|
||||||
__netif_tx_unlock_bh(txq);
|
__netif_tx_unlock_bh(txq);
|
||||||
|
|
||||||
/* If pkt_dev->count is zero, then run forever */
|
/* If pkt_dev->count is zero, then run forever */
|
||||||
if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
|
if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
|
||||||
while (atomic_read(&(pkt_dev->skb->users)) != 1) {
|
pktgen_wait_for_skb(pkt_dev);
|
||||||
if (signal_pending(current))
|
|
||||||
break;
|
|
||||||
idle(pkt_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Done with this */
|
/* Done with this */
|
||||||
pktgen_stop_device(pkt_dev);
|
pktgen_stop_device(pkt_dev);
|
||||||
|
@ -3515,20 +3503,24 @@ static int pktgen_thread_worker(void *arg)
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
pkt_dev = next_to_run(t);
|
pkt_dev = next_to_run(t);
|
||||||
|
|
||||||
if (!pkt_dev &&
|
if (unlikely(!pkt_dev && t->control == 0)) {
|
||||||
(t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV))
|
wait_event_interruptible_timeout(t->queue,
|
||||||
== 0) {
|
t->control != 0,
|
||||||
prepare_to_wait(&(t->queue), &wait,
|
HZ/10);
|
||||||
TASK_INTERRUPTIBLE);
|
continue;
|
||||||
schedule_timeout(HZ / 10);
|
|
||||||
finish_wait(&(t->queue), &wait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
if (pkt_dev)
|
if (likely(pkt_dev)) {
|
||||||
pktgen_xmit(pkt_dev);
|
pktgen_xmit(pkt_dev);
|
||||||
|
|
||||||
|
if (need_resched())
|
||||||
|
pktgen_resched(pkt_dev);
|
||||||
|
else
|
||||||
|
cpu_relax();
|
||||||
|
}
|
||||||
|
|
||||||
if (t->control & T_STOP) {
|
if (t->control & T_STOP) {
|
||||||
pktgen_stop(t);
|
pktgen_stop(t);
|
||||||
t->control &= ~(T_STOP);
|
t->control &= ~(T_STOP);
|
||||||
|
|
|
@ -66,10 +66,7 @@
|
||||||
solution, but it supposes maintaing new variable in ALL
|
solution, but it supposes maintaing new variable in ALL
|
||||||
skb, even if no tunneling is used.
|
skb, even if no tunneling is used.
|
||||||
|
|
||||||
Current solution: t->recursion lock breaks dead loops. It looks
|
Current solution: HARD_TX_LOCK lock breaks dead loops.
|
||||||
like dev->tbusy flag, but I preferred new variable, because
|
|
||||||
the semantics is different. One day, when hard_start_xmit
|
|
||||||
will be multithreaded we will have to use skb->encapsulation.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -678,11 +675,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
|
||||||
__be32 dst;
|
__be32 dst;
|
||||||
int mtu;
|
int mtu;
|
||||||
|
|
||||||
if (tunnel->recursion++) {
|
|
||||||
stats->collisions++;
|
|
||||||
goto tx_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dev->type == ARPHRD_ETHER)
|
if (dev->type == ARPHRD_ETHER)
|
||||||
IPCB(skb)->flags = 0;
|
IPCB(skb)->flags = 0;
|
||||||
|
|
||||||
|
@ -820,7 +812,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
|
||||||
ip_rt_put(rt);
|
ip_rt_put(rt);
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
if (skb->sk)
|
if (skb->sk)
|
||||||
|
@ -888,7 +879,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
|
||||||
nf_reset(skb);
|
nf_reset(skb);
|
||||||
|
|
||||||
IPTUNNEL_XMIT();
|
IPTUNNEL_XMIT();
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_error_icmp:
|
tx_error_icmp:
|
||||||
|
@ -897,7 +887,6 @@ tx_error_icmp:
|
||||||
tx_error:
|
tx_error:
|
||||||
stats->tx_errors++;
|
stats->tx_errors++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -611,6 +611,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
|
||||||
* Check the arguments are allowable
|
* Check the arguments are allowable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (optlen < sizeof(struct in_addr))
|
||||||
|
goto e_inval;
|
||||||
|
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
if (optlen >= sizeof(struct ip_mreqn)) {
|
if (optlen >= sizeof(struct ip_mreqn)) {
|
||||||
if (copy_from_user(&mreq, optval, sizeof(mreq)))
|
if (copy_from_user(&mreq, optval, sizeof(mreq)))
|
||||||
|
|
|
@ -402,11 +402,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
__be32 dst = tiph->daddr;
|
__be32 dst = tiph->daddr;
|
||||||
int mtu;
|
int mtu;
|
||||||
|
|
||||||
if (tunnel->recursion++) {
|
|
||||||
stats->collisions++;
|
|
||||||
goto tx_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skb->protocol != htons(ETH_P_IP))
|
if (skb->protocol != htons(ETH_P_IP))
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
|
|
||||||
|
@ -485,7 +480,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
ip_rt_put(rt);
|
ip_rt_put(rt);
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
if (skb->sk)
|
if (skb->sk)
|
||||||
|
@ -523,7 +517,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
nf_reset(skb);
|
nf_reset(skb);
|
||||||
|
|
||||||
IPTUNNEL_XMIT();
|
IPTUNNEL_XMIT();
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_error_icmp:
|
tx_error_icmp:
|
||||||
|
@ -531,7 +524,6 @@ tx_error_icmp:
|
||||||
tx_error:
|
tx_error:
|
||||||
stats->tx_errors++;
|
stats->tx_errors++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1043,11 +1043,6 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
struct net_device_stats *stats = &t->dev->stats;
|
struct net_device_stats *stats = &t->dev->stats;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (t->recursion++) {
|
|
||||||
stats->collisions++;
|
|
||||||
goto tx_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (skb->protocol) {
|
switch (skb->protocol) {
|
||||||
case htons(ETH_P_IP):
|
case htons(ETH_P_IP):
|
||||||
ret = ip4ip6_tnl_xmit(skb, dev);
|
ret = ip4ip6_tnl_xmit(skb, dev);
|
||||||
|
@ -1062,14 +1057,12 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto tx_err;
|
goto tx_err;
|
||||||
|
|
||||||
t->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_err:
|
tx_err:
|
||||||
stats->tx_errors++;
|
stats->tx_errors++;
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
t->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -626,11 +626,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
||||||
struct in6_addr *addr6;
|
struct in6_addr *addr6;
|
||||||
int addr_type;
|
int addr_type;
|
||||||
|
|
||||||
if (tunnel->recursion++) {
|
|
||||||
stats->collisions++;
|
|
||||||
goto tx_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skb->protocol != htons(ETH_P_IPV6))
|
if (skb->protocol != htons(ETH_P_IPV6))
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
|
|
||||||
|
@ -753,7 +748,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
||||||
ip_rt_put(rt);
|
ip_rt_put(rt);
|
||||||
stats->tx_dropped++;
|
stats->tx_dropped++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
if (skb->sk)
|
if (skb->sk)
|
||||||
|
@ -794,7 +788,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
||||||
nf_reset(skb);
|
nf_reset(skb);
|
||||||
|
|
||||||
IPTUNNEL_XMIT();
|
IPTUNNEL_XMIT();
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
tx_error_icmp:
|
tx_error_icmp:
|
||||||
|
@ -802,7 +795,6 @@ tx_error_icmp:
|
||||||
tx_error:
|
tx_error:
|
||||||
stats->tx_errors++;
|
stats->tx_errors++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
tunnel->recursion--;
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||||
bss->dtim_period = tim_ie->dtim_period;
|
bss->dtim_period = tim_ie->dtim_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set default value for buggy APs */
|
/* set default value for buggy AP/no TIM element */
|
||||||
if (!elems->tim || bss->dtim_period == 0)
|
if (bss->dtim_period == 0)
|
||||||
bss->dtim_period = 1;
|
bss->dtim_period = 1;
|
||||||
|
|
||||||
bss->supp_rates_len = 0;
|
bss->supp_rates_len = 0;
|
||||||
|
|
|
@ -1609,6 +1609,16 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
|
||||||
|
{
|
||||||
|
struct sock *sk;
|
||||||
|
struct hlist_node *node;
|
||||||
|
struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
|
||||||
|
|
||||||
|
sk_for_each_bound(sk, node, &tbl->mc_list)
|
||||||
|
netlink_update_socket_mc(nlk_sk(sk), group, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* netlink_clear_multicast_users - kick off multicast listeners
|
* netlink_clear_multicast_users - kick off multicast listeners
|
||||||
*
|
*
|
||||||
|
@ -1619,15 +1629,8 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
|
||||||
*/
|
*/
|
||||||
void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
|
void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
|
||||||
{
|
{
|
||||||
struct sock *sk;
|
|
||||||
struct hlist_node *node;
|
|
||||||
struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
|
|
||||||
|
|
||||||
netlink_table_grab();
|
netlink_table_grab();
|
||||||
|
__netlink_clear_multicast_users(ksk, group);
|
||||||
sk_for_each_bound(sk, node, &tbl->mc_list)
|
|
||||||
netlink_update_socket_mc(nlk_sk(sk), group, 0);
|
|
||||||
|
|
||||||
netlink_table_ungrab();
|
netlink_table_ungrab();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,10 +220,12 @@ static void __genl_unregister_mc_group(struct genl_family *family,
|
||||||
struct net *net;
|
struct net *net;
|
||||||
BUG_ON(grp->family != family);
|
BUG_ON(grp->family != family);
|
||||||
|
|
||||||
|
netlink_table_grab();
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for_each_net_rcu(net)
|
for_each_net_rcu(net)
|
||||||
netlink_clear_multicast_users(net->genl_sock, grp->id);
|
__netlink_clear_multicast_users(net->genl_sock, grp->id);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
netlink_table_ungrab();
|
||||||
|
|
||||||
clear_bit(grp->id, mc_groups);
|
clear_bit(grp->id, mc_groups);
|
||||||
list_del(&grp->list);
|
list_del(&grp->list);
|
||||||
|
|
|
@ -168,6 +168,12 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Broadcast sending is not implemented */
|
||||||
|
if (pn_addr(dst) == PNADDR_BROADCAST) {
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
|
||||||
skb_reset_transport_header(skb);
|
skb_reset_transport_header(skb);
|
||||||
WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
|
WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
|
||||||
skb_push(skb, sizeof(struct phonethdr));
|
skb_push(skb, sizeof(struct phonethdr));
|
||||||
|
|
|
@ -113,6 +113,8 @@ void pn_sock_unhash(struct sock *sk)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pn_sock_unhash);
|
EXPORT_SYMBOL(pn_sock_unhash);
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(port_mutex);
|
||||||
|
|
||||||
static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
|
static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
@ -140,9 +142,11 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
|
||||||
err = -EINVAL; /* attempt to rebind */
|
err = -EINVAL; /* attempt to rebind */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
WARN_ON(sk_hashed(sk));
|
||||||
|
mutex_lock(&port_mutex);
|
||||||
err = sk->sk_prot->get_port(sk, pn_port(handle));
|
err = sk->sk_prot->get_port(sk, pn_port(handle));
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out_port;
|
||||||
|
|
||||||
/* get_port() sets the port, bind() sets the address if applicable */
|
/* get_port() sets the port, bind() sets the address if applicable */
|
||||||
pn->sobject = pn_object(saddr, pn_port(pn->sobject));
|
pn->sobject = pn_object(saddr, pn_port(pn->sobject));
|
||||||
|
@ -150,6 +154,8 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
|
||||||
|
|
||||||
/* Enable RX on the socket */
|
/* Enable RX on the socket */
|
||||||
sk->sk_prot->hash(sk);
|
sk->sk_prot->hash(sk);
|
||||||
|
out_port:
|
||||||
|
mutex_unlock(&port_mutex);
|
||||||
out:
|
out:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return err;
|
return err;
|
||||||
|
@ -357,8 +363,6 @@ const struct proto_ops phonet_stream_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(phonet_stream_ops);
|
EXPORT_SYMBOL(phonet_stream_ops);
|
||||||
|
|
||||||
static DEFINE_MUTEX(port_mutex);
|
|
||||||
|
|
||||||
/* allocate port for a socket */
|
/* allocate port for a socket */
|
||||||
int pn_sock_get_port(struct sock *sk, unsigned short sport)
|
int pn_sock_get_port(struct sock *sk, unsigned short sport)
|
||||||
{
|
{
|
||||||
|
@ -370,9 +374,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
|
||||||
|
|
||||||
memset(&try_sa, 0, sizeof(struct sockaddr_pn));
|
memset(&try_sa, 0, sizeof(struct sockaddr_pn));
|
||||||
try_sa.spn_family = AF_PHONET;
|
try_sa.spn_family = AF_PHONET;
|
||||||
|
WARN_ON(!mutex_is_locked(&port_mutex));
|
||||||
mutex_lock(&port_mutex);
|
|
||||||
|
|
||||||
if (!sport) {
|
if (!sport) {
|
||||||
/* search free port */
|
/* search free port */
|
||||||
int port, pmin, pmax;
|
int port, pmin, pmax;
|
||||||
|
@ -401,8 +403,6 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
|
||||||
else
|
else
|
||||||
sock_put(tmpsk);
|
sock_put(tmpsk);
|
||||||
}
|
}
|
||||||
mutex_unlock(&port_mutex);
|
|
||||||
|
|
||||||
/* the port must be in use already */
|
/* the port must be in use already */
|
||||||
return -EADDRINUSE;
|
return -EADDRINUSE;
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
|
||||||
|
|
||||||
wdev->wext.connect.ie = wdev->wext.ie;
|
wdev->wext.connect.ie = wdev->wext.ie;
|
||||||
wdev->wext.connect.ie_len = wdev->wext.ie_len;
|
wdev->wext.connect.ie_len = wdev->wext.ie_len;
|
||||||
wdev->wext.connect.privacy = wdev->wext.default_key != -1;
|
|
||||||
|
|
||||||
if (wdev->wext.keys) {
|
if (wdev->wext.keys) {
|
||||||
wdev->wext.keys->def = wdev->wext.default_key;
|
wdev->wext.keys->def = wdev->wext.default_key;
|
||||||
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
|
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
|
||||||
|
wdev->wext.connect.privacy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wdev->wext.connect.ssid_len)
|
if (!wdev->wext.connect.ssid_len)
|
||||||
|
|
Loading…
Add table
Reference in a new issue