diff options
-rw-r--r-- | share/man/man4/arcmsr.4 | 4 | ||||
-rw-r--r-- | sys/dev/arcmsr/arcmsr.c | 85 | ||||
-rw-r--r-- | sys/dev/arcmsr/arcmsr.h | 8 |
3 files changed, 58 insertions, 39 deletions
diff --git a/share/man/man4/arcmsr.4 b/share/man/man4/arcmsr.4 index 87c7050..1d4d650 100644 --- a/share/man/man4/arcmsr.4 +++ b/share/man/man4/arcmsr.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 27, 2013 +.Dd December 18, 2013 .Dt ARCMSR 4 .Os .Sh NAME @@ -143,6 +143,8 @@ ARC-1681 ARC-1880 .It ARC-1882 +.It +ARC-1883 .El .Sh FILES .Bl -tag -width ".Pa /dev/arcmsr?" -compact diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 7e993e7..5b23acc 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -75,6 +75,7 @@ ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 ** 1.20.00.28 09/13/2013 Ching Huang Removed recursive mutex in arcmsr_abort_dr_ccbs +** 1.20.00.29 12/18/2013 Ching Huang Change simq allocation number, support ARC1883 ****************************************************************************************** */ @@ -146,7 +147,7 @@ __FBSDID("$FreeBSD$"); #define arcmsr_callout_init(a) callout_init(a); #endif -#define ARCMSR_DRIVER_VERSION "arcmsr version 1.20.00.28 2013-09-13" +#define ARCMSR_DRIVER_VERSION "arcmsr version 1.20.00.29 2013-12-18" #include <dev/arcmsr/arcmsr.h> /* ************************************************************************** @@ -1438,7 +1439,7 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, u_int8_t *iop_data; u_int32_t iop_len; - if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { + if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); } iop_data = (u_int8_t *)prbuffer->data; @@ -1533,7 +1534,7 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) u_int8_t *iop_data; int32_t allxfer_len=0; - if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { + if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { arcmsr_Write_data_2iop_wqbuffer_D(acb); return; } @@ -1785,7 +1786,7 @@ static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { */ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1794,14 +1795,12 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, - 0, outbound_doorbell); - CHIP_REG_WRITE32(HBA_MessageUnit, - 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); + CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ + if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } } @@ -1811,7 +1810,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) */ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1820,15 +1819,15 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); - CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); + CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } - if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { + if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ } } @@ -1838,7 +1837,7 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) */ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) { - u_int32_t outbound_Doorbell; + u_int32_t doorbell_status; /* ******************************************************************* @@ -1847,22 +1846,22 @@ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) ** check if there are any mail need to pack from firmware ******************************************************************* */ - outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; - if(outbound_Doorbell) - CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ - while( outbound_Doorbell & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { + doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; + if(doorbell_status) + CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ + while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { arcmsr_iop2drv_data_wrote_handle(acb); } - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { arcmsr_iop2drv_data_read_handle(acb); } - if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { + if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ } - outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; - if(outbound_Doorbell) - CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ + doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; + if(doorbell_status) + CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ } } /* @@ -1932,9 +1931,7 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) ***************************************************************************** */ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - - while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { - + do { flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); /* check if command done with no error*/ error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; @@ -1944,7 +1941,7 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); throttling = 0; } - } /*drain reply FIFO*/ + } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); } /* ********************************************************************** @@ -2082,11 +2079,14 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) ** check outbound intstatus ********************************************* */ - host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); + host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & + (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | + ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); if(!host_interrupt_status) { /*it must be share irq*/ return; } + do { /* MU doorbell interrupts*/ if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { arcmsr_hbc_doorbell_isr(acb); @@ -2095,6 +2095,8 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { arcmsr_hbc_postqueue_isr(acb); } + host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); + } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); } /* ********************************************************************** @@ -2882,7 +2884,9 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(psim); #ifdef CAM_NEW_TRAN_CODE - if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) + if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) + cpi->base_transfer_speed = 1200000; + else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) cpi->base_transfer_speed = 600000; else cpi->base_transfer_speed = 300000; @@ -2980,7 +2984,9 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) cts->transport = XPORT_SAS; sas = &cts->xport_specific.sas; sas->valid = CTS_SAS_VALID_SPEED; - if((acb->vendor_device_id == PCIDevVenIDARC1880) || + if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) + sas->bitrate = 1200000; + else if((acb->vendor_device_id == PCIDevVenIDARC1880) || (acb->vendor_device_id == PCIDevVenIDARC1214)) sas->bitrate = 600000; else if(acb->vendor_device_id == PCIDevVenIDARC1680) @@ -3948,12 +3954,16 @@ static u_int32_t arcmsr_initialize(device_t dev) vendor_dev_id = pci_get_devid(dev); acb->vendor_device_id = vendor_dev_id; + acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); switch (vendor_dev_id) { case PCIDevVenIDARC1880: case PCIDevVenIDARC1882: case PCIDevVenIDARC1213: case PCIDevVenIDARC1223: { acb->adapter_type = ACB_ADAPTER_TYPE_C; + if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) + acb->adapter_bus_speed = ACB_BUS_SPEED_12G; + else acb->adapter_bus_speed = ACB_BUS_SPEED_6G; max_coherent_size = ARCMSR_SRBS_POOL_SIZE; } @@ -4286,7 +4296,7 @@ static int arcmsr_attach(device_t dev) * Create device queue of SIM(s) * (MAX_START_JOB - 1) : * max_sim_transactions */ - devq = cam_simq_alloc(ARCMSR_MAX_START_JOB); + devq = cam_simq_alloc(acb->maxOutstanding); if(devq == NULL) { arcmsr_free_resource(acb); bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); @@ -4360,6 +4370,7 @@ static int arcmsr_attach(device_t dev) static int arcmsr_probe(device_t dev) { u_int32_t id; + u_int16_t sub_device_id; static char buf[256]; char x_type[]={"unknown"}; char *type; @@ -4368,6 +4379,7 @@ static int arcmsr_probe(device_t dev) if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { return (ENXIO); } + sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); switch(id = pci_get_devid(dev)) { case PCIDevVenIDARC1110: case PCIDevVenIDARC1200: @@ -4400,6 +4412,9 @@ static int arcmsr_probe(device_t dev) case PCIDevVenIDARC1882: case PCIDevVenIDARC1213: case PCIDevVenIDARC1223: + if (sub_device_id == ARECA_SUB_DEV_ID_1883) + type = "SAS 12G"; + else type = "SAS 6G"; break; case PCIDevVenIDARC1214: diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h index e4f2d6f..d3aa5d3 100644 --- a/sys/dev/arcmsr/arcmsr.h +++ b/sys/dev/arcmsr/arcmsr.h @@ -118,6 +118,7 @@ #define ARECA_SUB_DEV_ID_1880 0x1880 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1882 0x1882 /* Subsystem Device ID */ +#define ARECA_SUB_DEV_ID_1883 0x1883 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1212 0x1212 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1213 0x1213 /* Subsystem Device ID */ #define ARECA_SUB_DEV_ID_1222 0x1222 /* Subsystem Device ID */ @@ -1136,16 +1137,16 @@ struct AdapterControlBlock { u_int32_t phyadd_low; u_int32_t phyadd_high; }B; - } srb_phyaddr; + }srb_phyaddr; // unsigned long srb_phyaddr; /* Offset is used in making arc cdb physical to virtual calculations */ u_int32_t outbound_int_enable; struct MessageUnit_UNION *pmu; /* message unit ATU inbound base address0 */ - u_int8_t adapter_index; /* */ + u_int8_t adapter_index; u_int8_t irq; - u_int16_t acb_flags; /* */ + u_int16_t acb_flags; struct CommandControlBlock *psrb_pool[ARCMSR_MAX_FREESRB_NUM]; /* serial srb pointer array */ struct CommandControlBlock *srbworkingQ[ARCMSR_MAX_FREESRB_NUM]; /* working srb pointer array */ @@ -1183,6 +1184,7 @@ struct AdapterControlBlock { u_int32_t vendor_device_id; u_int32_t adapter_bus_speed; u_int32_t maxOutstanding; + u_int16_t sub_device_id; };/* HW_DEVICE_EXTENSION */ /* acb_flags */ #define ACB_F_SCSISTOPADAPTER 0x0001 |